Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
b235b48d
Commit
b235b48d
authored
Feb 26, 2017
by
astaxie
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' of
https://github.com/astaxie/beego
into develop
parents
28011a58
b03b0779
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
457 additions
and
179 deletions
+457
-179
file.go
cache/file.go
+3
-22
config.go
config.go
+3
-1
env.go
config/env/env.go
+85
-0
env_test.go
config/env/env_test.go
+75
-0
ini.go
config/ini.go
+23
-20
xml.go
config/xml/xml.go
+8
-20
yaml.go
config/yaml/yaml.go
+13
-11
output.go
context/output.go
+5
-4
controller.go
controller.go
+12
-4
controller_test.go
controller_test.go
+58
-0
hooks.go
hooks.go
+2
-1
db.go
orm/db.go
+1
-0
orm_queryset.go
orm/orm_queryset.go
+5
-0
types.go
orm/types.go
+10
-0
apiauth.go
plugins/apiauth/apiauth.go
+16
-36
apiauth_test.go
plugins/apiauth/apiauth_test.go
+20
-0
router.go
router.go
+16
-9
sess_mysql.go
session/mysql/sess_mysql.go
+2
-0
sess_file.go
session/sess_file.go
+47
-36
template.go
template.go
+44
-14
template_test.go
template_test.go
+9
-1
No files found.
cache/file.go
View file @
b235b48d
...
...
@@ -22,6 +22,7 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
...
...
@@ -222,33 +223,13 @@ func exists(path string) (bool, error) {
// FileGetContents Get bytes to file.
// if non-exist, create this file.
func
FileGetContents
(
filename
string
)
(
data
[]
byte
,
e
error
)
{
f
,
e
:=
os
.
OpenFile
(
filename
,
os
.
O_RDWR
|
os
.
O_CREATE
,
os
.
ModePerm
)
if
e
!=
nil
{
return
}
defer
f
.
Close
()
stat
,
e
:=
f
.
Stat
()
if
e
!=
nil
{
return
}
data
=
make
([]
byte
,
stat
.
Size
())
result
,
e
:=
f
.
Read
(
data
)
if
e
!=
nil
||
int64
(
result
)
!=
stat
.
Size
()
{
return
nil
,
e
}
return
return
ioutil
.
ReadFile
(
filename
)
}
// FilePutContents Put bytes to file.
// if non-exist, create this file.
func
FilePutContents
(
filename
string
,
content
[]
byte
)
error
{
fp
,
err
:=
os
.
OpenFile
(
filename
,
os
.
O_RDWR
|
os
.
O_CREATE
,
os
.
ModePerm
)
if
err
!=
nil
{
return
err
}
defer
fp
.
Close
()
_
,
err
=
fp
.
Write
(
content
)
return
err
return
ioutil
.
WriteFile
(
filename
,
content
,
os
.
ModePerm
)
}
// GobEncode Gob encodes file cache item.
...
...
config.go
View file @
b235b48d
...
...
@@ -41,6 +41,7 @@ type Config struct {
EnableGzip
bool
MaxMemory
int64
EnableErrorsShow
bool
EnableErrorsRender
bool
Listen
Listen
WebConfig
WebConfig
Log
LogConfig
...
...
@@ -171,7 +172,7 @@ func recoverPanic(ctx *context.Context) {
logs
.
Critical
(
fmt
.
Sprintf
(
"%s:%d"
,
file
,
line
))
stack
=
stack
+
fmt
.
Sprintln
(
fmt
.
Sprintf
(
"%s:%d"
,
file
,
line
))
}
if
BConfig
.
RunMode
==
DEV
{
if
BConfig
.
RunMode
==
DEV
&&
BConfig
.
EnableErrorsRender
{
showErr
(
err
,
ctx
,
stack
)
}
}
...
...
@@ -189,6 +190,7 @@ func newBConfig() *Config {
EnableGzip
:
false
,
MaxMemory
:
1
<<
26
,
//64MB
EnableErrorsShow
:
true
,
EnableErrorsRender
:
true
,
Listen
:
Listen
{
Graceful
:
false
,
ServerTimeOut
:
0
,
...
...
config/env/env.go
0 → 100644
View file @
b235b48d
// Copyright 2014 beego Author. All Rights Reserved.
// Copyright 2017 Faissal Elamraoui. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
env
import
(
"fmt"
"os"
"strings"
"github.com/astaxie/beego/utils"
)
var
env
*
utils
.
BeeMap
func
init
()
{
env
=
utils
.
NewBeeMap
()
for
_
,
e
:=
range
os
.
Environ
()
{
splits
:=
strings
.
Split
(
e
,
"="
)
env
.
Set
(
splits
[
0
],
os
.
Getenv
(
splits
[
0
]))
}
}
// Get returns a value by key.
// If the key does not exist, the default value will be returned.
func
Get
(
key
string
,
defVal
string
)
string
{
if
val
:=
env
.
Get
(
key
);
val
!=
nil
{
return
val
.
(
string
)
}
return
defVal
}
// MustGet returns a value by key.
// If the key does not exist, it will return an error.
func
MustGet
(
key
string
)
(
string
,
error
)
{
if
val
:=
env
.
Get
(
key
);
val
!=
nil
{
return
val
.
(
string
),
nil
}
return
""
,
fmt
.
Errorf
(
"no env variable with %s"
,
key
)
}
// Set sets a value in the ENV copy.
// This does not affect the child process environment.
func
Set
(
key
string
,
value
string
)
{
env
.
Set
(
key
,
value
)
}
// MustSet sets a value in the ENV copy and the child process environment.
// It returns an error in case the set operation failed.
func
MustSet
(
key
string
,
value
string
)
error
{
err
:=
os
.
Setenv
(
key
,
value
)
if
err
!=
nil
{
return
err
}
env
.
Set
(
key
,
value
)
return
nil
}
// GetAll returns all keys/values in the current child process environment.
func
GetAll
()
map
[
string
]
string
{
items
:=
env
.
Items
()
envs
:=
make
(
map
[
string
]
string
,
env
.
Count
())
for
key
,
val
:=
range
items
{
switch
key
:=
key
.
(
type
)
{
case
string
:
switch
val
:=
val
.
(
type
)
{
case
string
:
envs
[
key
]
=
val
}
}
}
return
envs
}
config/env/env_test.go
0 → 100644
View file @
b235b48d
// Copyright 2014 beego Author. All Rights Reserved.
// Copyright 2017 Faissal Elamraoui. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
env
import
(
"os"
"testing"
)
func
TestEnvGet
(
t
*
testing
.
T
)
{
gopath
:=
Get
(
"GOPATH"
,
""
)
if
gopath
!=
os
.
Getenv
(
"GOPATH"
)
{
t
.
Error
(
"expected GOPATH not empty."
)
}
noExistVar
:=
Get
(
"NOEXISTVAR"
,
"foo"
)
if
noExistVar
!=
"foo"
{
t
.
Errorf
(
"expected NOEXISTVAR to equal foo, got %s."
,
noExistVar
)
}
}
func
TestEnvMustGet
(
t
*
testing
.
T
)
{
gopath
,
err
:=
MustGet
(
"GOPATH"
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
if
gopath
!=
os
.
Getenv
(
"GOPATH"
)
{
t
.
Errorf
(
"expected GOPATH to be the same, got %s."
,
gopath
)
}
_
,
err
=
MustGet
(
"NOEXISTVAR"
)
if
err
==
nil
{
t
.
Error
(
"expected error to be non-nil"
)
}
}
func
TestEnvSet
(
t
*
testing
.
T
)
{
Set
(
"MYVAR"
,
"foo"
)
myVar
:=
Get
(
"MYVAR"
,
"bar"
)
if
myVar
!=
"foo"
{
t
.
Errorf
(
"expected MYVAR to equal foo, got %s."
,
myVar
)
}
}
func
TestEnvMustSet
(
t
*
testing
.
T
)
{
err
:=
MustSet
(
"FOO"
,
"bar"
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
fooVar
:=
os
.
Getenv
(
"FOO"
)
if
fooVar
!=
"bar"
{
t
.
Errorf
(
"expected FOO variable to equal bar, got %s."
,
fooVar
)
}
}
func
TestEnvGetAll
(
t
*
testing
.
T
)
{
envMap
:=
GetAll
()
if
len
(
envMap
)
==
0
{
t
.
Error
(
"expected environment not empty."
)
}
}
config/ini.go
View file @
b235b48d
...
...
@@ -18,16 +18,13 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
)
var
(
...
...
@@ -52,24 +49,26 @@ func (ini *IniConfig) Parse(name string) (Configer, error) {
}
func
(
ini
*
IniConfig
)
parseFile
(
name
string
)
(
*
IniConfigContainer
,
error
)
{
file
,
err
:=
os
.
Open
(
name
)
data
,
err
:=
ioutil
.
ReadFile
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
return
ini
.
parseData
(
data
)
}
func
(
ini
*
IniConfig
)
parseData
(
data
[]
byte
)
(
*
IniConfigContainer
,
error
)
{
cfg
:=
&
IniConfigContainer
{
file
.
Name
(),
make
(
map
[
string
]
map
[
string
]
string
),
make
(
map
[
string
]
string
),
make
(
map
[
string
]
string
),
sync
.
RWMutex
{},
data
:
make
(
map
[
string
]
map
[
string
]
string
),
sectionComment
:
make
(
map
[
string
]
string
),
keyComment
:
make
(
map
[
string
]
string
),
RWMutex
:
sync
.
RWMutex
{},
}
cfg
.
Lock
()
defer
cfg
.
Unlock
()
defer
file
.
Close
()
var
comment
bytes
.
Buffer
buf
:=
bufio
.
NewReader
(
file
)
buf
:=
bufio
.
NewReader
(
bytes
.
NewBuffer
(
data
)
)
// check the BOM
head
,
err
:=
buf
.
Peek
(
3
)
if
err
==
nil
&&
head
[
0
]
==
239
&&
head
[
1
]
==
187
&&
head
[
2
]
==
191
{
...
...
@@ -130,16 +129,24 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
// handle include "other.conf"
if
len
(
keyValue
)
==
1
&&
strings
.
HasPrefix
(
key
,
"include"
)
{
includefiles
:=
strings
.
Fields
(
key
)
if
includefiles
[
0
]
==
"include"
&&
len
(
includefiles
)
==
2
{
otherfile
:=
strings
.
Trim
(
includefiles
[
1
],
"
\"
"
)
if
!
filepath
.
IsAbs
(
otherfile
)
{
otherfile
=
filepath
.
Join
(
filepath
.
Dir
(
name
),
otherfile
)
dir
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
return
nil
,
err
}
otherfile
=
filepath
.
Join
(
dir
,
otherfile
)
}
i
,
err
:=
ini
.
parseFile
(
otherfile
)
if
err
!=
nil
{
return
nil
,
err
}
for
sec
,
dt
:=
range
i
.
data
{
if
_
,
ok
:=
cfg
.
data
[
sec
];
!
ok
{
cfg
.
data
[
sec
]
=
make
(
map
[
string
]
string
)
...
...
@@ -148,12 +155,15 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
cfg
.
data
[
sec
][
k
]
=
v
}
}
for
sec
,
comm
:=
range
i
.
sectionComment
{
cfg
.
sectionComment
[
sec
]
=
comm
}
for
k
,
comm
:=
range
i
.
keyComment
{
cfg
.
keyComment
[
k
]
=
comm
}
continue
}
}
...
...
@@ -178,19 +188,12 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
// ParseData parse ini the data
func
(
ini
*
IniConfig
)
ParseData
(
data
[]
byte
)
(
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
if
err
:=
ioutil
.
WriteFile
(
tmpName
,
data
,
0655
);
err
!=
nil
{
return
nil
,
err
}
return
ini
.
Parse
(
tmpName
)
return
ini
.
parseData
(
data
)
}
// IniConfigContainer A Config represents the ini configuration.
// When set and get value, support key as section:name type.
type
IniConfigContainer
struct
{
filename
string
data
map
[
string
]
map
[
string
]
string
// section=> key:val
sectionComment
map
[
string
]
string
// section : comment
keyComment
map
[
string
]
string
// id: []{comment, key...}; id 1 is for main comment.
...
...
config/xml/xml.go
View file @
b235b48d
...
...
@@ -35,11 +35,9 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
"sync"
"time"
"github.com/astaxie/beego/config"
"github.com/beego/x2j"
...
...
@@ -52,36 +50,26 @@ type Config struct{}
// Parse returns a ConfigContainer with parsed xml config map.
func
(
xc
*
Config
)
Parse
(
filename
string
)
(
config
.
Configer
,
error
)
{
file
,
err
:=
os
.
Open
(
filename
)
context
,
err
:=
ioutil
.
ReadFile
(
filename
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
return
xc
.
ParseData
(
context
)
}
// ParseData xml data
func
(
xc
*
Config
)
ParseData
(
data
[]
byte
)
(
config
.
Configer
,
error
)
{
x
:=
&
ConfigContainer
{
data
:
make
(
map
[
string
]
interface
{})}
content
,
err
:=
ioutil
.
ReadAll
(
file
)
if
err
!=
nil
{
return
nil
,
err
}
d
,
err
:=
x2j
.
DocToMap
(
string
(
content
))
d
,
err
:=
x2j
.
DocToMap
(
string
(
data
))
if
err
!=
nil
{
return
nil
,
err
}
x
.
data
=
config
.
ExpandValueEnvForMap
(
d
[
"config"
]
.
(
map
[
string
]
interface
{}))
return
x
,
nil
}
// ParseData xml data
func
(
xc
*
Config
)
ParseData
(
data
[]
byte
)
(
config
.
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
if
err
:=
ioutil
.
WriteFile
(
tmpName
,
data
,
0655
);
err
!=
nil
{
return
nil
,
err
}
return
xc
.
Parse
(
tmpName
)
return
x
,
nil
}
// ConfigContainer A Config represents the xml configuration.
...
...
config/yaml/yaml.go
View file @
b235b48d
...
...
@@ -37,10 +37,8 @@ import (
"io/ioutil"
"log"
"os"
"path"
"strings"
"sync"
"time"
"github.com/astaxie/beego/config"
"github.com/beego/goyaml2"
...
...
@@ -63,26 +61,30 @@ func (yaml *Config) Parse(filename string) (y config.Configer, err error) {
// ParseData parse yaml data
func
(
yaml
*
Config
)
ParseData
(
data
[]
byte
)
(
config
.
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
if
err
:=
ioutil
.
WriteFile
(
tmpName
,
data
,
0655
);
err
!=
nil
{
cnf
,
err
:=
parseYML
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
return
yaml
.
Parse
(
tmpName
)
return
&
ConfigContainer
{
data
:
cnf
,
},
nil
}
// ReadYmlReader Read yaml file to map.
// if json like, use json package, unless goyaml2 package.
func
ReadYmlReader
(
path
string
)
(
cnf
map
[
string
]
interface
{},
err
error
)
{
f
,
err
:=
os
.
Open
(
path
)
buf
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
}
defer
f
.
Close
()
buf
,
err
:=
ioutil
.
ReadAll
(
f
)
if
err
!=
nil
||
len
(
buf
)
<
3
{
return
parseYML
(
buf
)
}
// parseYML parse yaml formatted []byte to map.
func
parseYML
(
buf
[]
byte
)
(
cnf
map
[
string
]
interface
{},
err
error
)
{
if
len
(
buf
)
<
3
{
return
}
...
...
context/output.go
View file @
b235b48d
...
...
@@ -331,16 +331,17 @@ func (output *BeegoOutput) IsServerError() bool {
func
stringsToJSON
(
str
string
)
string
{
rs
:=
[]
rune
(
str
)
jsons
:=
""
var
jsons
bytes
.
Buffer
for
_
,
r
:=
range
rs
{
rint
:=
int
(
r
)
if
rint
<
128
{
jsons
+=
string
(
r
)
jsons
.
WriteRune
(
r
)
}
else
{
jsons
+=
"
\\
u"
+
strconv
.
FormatInt
(
int64
(
rint
),
16
)
// json
jsons
.
WriteString
(
"
\\
u"
)
jsons
.
WriteString
(
strconv
.
FormatInt
(
int64
(
rint
),
16
))
}
}
return
jsons
return
jsons
.
String
()
}
// Session sets session item value with given key.
...
...
controller.go
View file @
b235b48d
...
...
@@ -69,6 +69,7 @@ type Controller struct {
// template data
TplName
string
ViewPath
string
Layout
string
LayoutSections
map
[
string
]
string
// the key is the section name and the value is the template name
TplPrefix
string
...
...
@@ -213,7 +214,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
continue
}
buf
.
Reset
()
err
=
Execute
Template
(
&
buf
,
sectionTpl
,
c
.
Data
)
err
=
Execute
ViewPathTemplate
(
&
buf
,
sectionTpl
,
c
.
viewPath
()
,
c
.
Data
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -222,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
}
buf
.
Reset
()
Execute
Template
(
&
buf
,
c
.
Layout
,
c
.
Data
)
Execute
ViewPathTemplate
(
&
buf
,
c
.
Layout
,
c
.
viewPath
()
,
c
.
Data
)
}
return
buf
.
Bytes
(),
err
}
...
...
@@ -248,9 +249,16 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) {
}
}
}
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
,
buildFiles
...
)
BuildTemplate
(
c
.
viewPath
()
,
buildFiles
...
)
}
return
buf
,
ExecuteTemplate
(
&
buf
,
c
.
TplName
,
c
.
Data
)
return
buf
,
ExecuteViewPathTemplate
(
&
buf
,
c
.
TplName
,
c
.
viewPath
(),
c
.
Data
)
}
func
(
c
*
Controller
)
viewPath
()
string
{
if
c
.
ViewPath
==
""
{
return
BConfig
.
WebConfig
.
ViewsPath
}
return
c
.
ViewPath
}
// Redirect sends the redirection response to url with status code.
...
...
controller_test.go
View file @
b235b48d
...
...
@@ -20,6 +20,8 @@ import (
"testing"
"github.com/astaxie/beego/context"
"os"
"path/filepath"
)
func
TestGetInt
(
t
*
testing
.
T
)
{
...
...
@@ -121,3 +123,59 @@ func TestGetUint64(t *testing.T) {
t
.
Errorf
(
"TestGetUint64 expect %v,get %T,%v"
,
uint64
(
math
.
MaxUint64
),
val
,
val
)
}
}
func
TestAdditionalViewPaths
(
t
*
testing
.
T
)
{
dir1
:=
"_beeTmp"
dir2
:=
"_beeTmp2"
defer
os
.
RemoveAll
(
dir1
)
defer
os
.
RemoveAll
(
dir2
)
dir1file
:=
"file1.tpl"
dir2file
:=
"file2.tpl"
genFile
:=
func
(
dir
string
,
name
string
,
content
string
)
{
os
.
MkdirAll
(
filepath
.
Dir
(
filepath
.
Join
(
dir
,
name
)),
0777
)
if
f
,
err
:=
os
.
Create
(
filepath
.
Join
(
dir
,
name
));
err
!=
nil
{
t
.
Fatal
(
err
)
}
else
{
defer
f
.
Close
()
f
.
WriteString
(
content
)
f
.
Close
()
}
}
genFile
(
dir1
,
dir1file
,
`<div>{{.Content}}</div>`
)
genFile
(
dir2
,
dir2file
,
`<html>{{.Content}}</html>`
)
AddViewPath
(
dir1
)
AddViewPath
(
dir2
)
ctrl
:=
Controller
{
TplName
:
"file1.tpl"
,
ViewPath
:
dir1
,
}
ctrl
.
Data
=
map
[
interface
{}]
interface
{}{
"Content"
:
"value2"
,
}
if
result
,
err
:=
ctrl
.
RenderString
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
else
{
if
result
!=
"<div>value2</div>"
{
t
.
Fatalf
(
"TestAdditionalViewPaths expect %s got %s"
,
"<div>value2</div>"
,
result
)
}
}
func
()
{
ctrl
.
TplName
=
"file2.tpl"
defer
func
()
{
if
r
:=
recover
();
r
==
nil
{
t
.
Fatal
(
"TestAdditionalViewPaths expected error"
)
}
}()
ctrl
.
RenderString
();
}()
ctrl
.
TplName
=
"file2.tpl"
ctrl
.
ViewPath
=
dir2
ctrl
.
RenderString
();
}
hooks.go
View file @
b235b48d
...
...
@@ -72,7 +72,8 @@ func registerSession() error {
}
func
registerTemplate
()
error
{
if
err
:=
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
defer
lockViewPaths
()
if
err
:=
AddViewPath
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
if
BConfig
.
RunMode
==
DEV
{
logs
.
Warn
(
err
)
}
...
...
orm/db.go
View file @
b235b48d
...
...
@@ -48,6 +48,7 @@ var (
"lte"
:
true
,
"eq"
:
true
,
"nq"
:
true
,
"ne"
:
true
,
"startswith"
:
true
,
"endswith"
:
true
,
"istartswith"
:
true
,
...
...
orm/orm_queryset.go
View file @
b235b48d
...
...
@@ -153,6 +153,11 @@ func (o querySet) SetCond(cond *Condition) QuerySeter {
return
&
o
}
// get condition from QuerySeter
func
(
o
querySet
)
GetCond
()
*
Condition
{
return
o
.
cond
}
// return QuerySeter execution result number
func
(
o
*
querySet
)
Count
()
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
Count
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
o
.
orm
.
alias
.
TZ
)
...
...
orm/types.go
View file @
b235b48d
...
...
@@ -145,6 +145,16 @@ type QuerySeter interface {
// //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` > 2000
// num, err := qs.SetCond(cond1).Count()
SetCond
(
*
Condition
)
QuerySeter
// get condition from QuerySeter.
// sql's where condition
// cond := orm.NewCondition()
// cond = cond.And("profile__isnull", false).AndNot("status__in", 1)
// qs = qs.SetCond(cond)
// cond = qs.GetCond()
// cond := cond.Or("profile__age__gt", 2000)
// //sql-> WHERE T0.`profile_id` IS NOT NULL AND NOT T0.`Status` IN (?) OR T1.`age` > 2000
// num, err := qs.SetCond(cond).Count()
GetCond
()
*
Condition
// add LIMIT value.
// args[0] means offset, e.g. LIMIT num,offset.
// if Limit <= 0 then Limit will be set to default limit ,eg 1000
...
...
plugins/apiauth/apiauth.go
View file @
b235b48d
...
...
@@ -56,6 +56,7 @@
package
apiauth
import
(
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
...
...
@@ -128,53 +129,32 @@ func APISecretAuth(f AppIDToAppSecret, timeout int) beego.FilterFunc {
// Signature used to generate signature with the appsecret/method/params/RequestURI
func
Signature
(
appsecret
,
method
string
,
params
url
.
Values
,
RequestURL
string
)
(
result
string
)
{
var
query
string
var
b
bytes
.
Buffer
keys
:=
make
([]
string
,
len
(
params
))
pa
:=
make
(
map
[
string
]
string
)
for
k
,
v
:=
range
params
{
pa
[
k
]
=
v
[
0
]
keys
=
append
(
keys
,
k
)
}
vs
:=
mapSorter
(
pa
)
vs
.
Sort
()
for
i
:=
0
;
i
<
vs
.
Len
();
i
++
{
if
vs
.
Keys
[
i
]
==
"signature"
{
sort
.
Strings
(
keys
)
for
_
,
key
:=
range
keys
{
if
key
==
"signature"
{
continue
}
if
vs
.
Keys
[
i
]
!=
""
&&
vs
.
Vals
[
i
]
!=
""
{
query
=
fmt
.
Sprintf
(
"%v%v%v"
,
query
,
vs
.
Keys
[
i
],
vs
.
Vals
[
i
])
val
:=
pa
[
key
]
if
key
!=
""
&&
val
!=
""
{
b
.
WriteString
(
key
)
b
.
WriteString
(
val
)
}
}
stringToSign
:=
fmt
.
Sprintf
(
"%v
\n
%v
\n
%v
\n
"
,
method
,
query
,
RequestURL
)
stringToSign
:=
fmt
.
Sprintf
(
"%v
\n
%v
\n
%v
\n
"
,
method
,
b
.
String
(),
RequestURL
)
sha256
:=
sha256
.
New
hash
:=
hmac
.
New
(
sha256
,
[]
byte
(
appsecret
))
hash
.
Write
([]
byte
(
stringToSign
))
return
base64
.
StdEncoding
.
EncodeToString
(
hash
.
Sum
(
nil
))
}
type
valSorter
struct
{
Keys
[]
string
Vals
[]
string
}
func
mapSorter
(
m
map
[
string
]
string
)
*
valSorter
{
vs
:=
&
valSorter
{
Keys
:
make
([]
string
,
0
,
len
(
m
)),
Vals
:
make
([]
string
,
0
,
len
(
m
)),
}
for
k
,
v
:=
range
m
{
vs
.
Keys
=
append
(
vs
.
Keys
,
k
)
vs
.
Vals
=
append
(
vs
.
Vals
,
v
)
}
return
vs
}
func
(
vs
*
valSorter
)
Sort
()
{
sort
.
Sort
(
vs
)
}
func
(
vs
*
valSorter
)
Len
()
int
{
return
len
(
vs
.
Keys
)
}
func
(
vs
*
valSorter
)
Less
(
i
,
j
int
)
bool
{
return
vs
.
Keys
[
i
]
<
vs
.
Keys
[
j
]
}
func
(
vs
*
valSorter
)
Swap
(
i
,
j
int
)
{
vs
.
Vals
[
i
],
vs
.
Vals
[
j
]
=
vs
.
Vals
[
j
],
vs
.
Vals
[
i
]
vs
.
Keys
[
i
],
vs
.
Keys
[
j
]
=
vs
.
Keys
[
j
],
vs
.
Keys
[
i
]
}
plugins/apiauth/apiauth_test.go
0 → 100644
View file @
b235b48d
package
apiauth
import
(
"net/url"
"testing"
)
func
TestSignature
(
t
*
testing
.
T
)
{
appsecret
:=
"beego secret"
method
:=
"GET"
RequestURL
:=
"http://localhost/test/url"
params
:=
make
(
url
.
Values
)
params
.
Add
(
"arg1"
,
"hello"
)
params
.
Add
(
"arg2"
,
"beego"
)
signature
:=
"mFdpvLh48ca4mDVEItE9++AKKQ/IVca7O/ZyyB8hR58="
if
Signature
(
appsecret
,
method
,
params
,
RequestURL
)
!=
signature
{
t
.
Error
(
"Signature error"
)
}
}
router.go
View file @
b235b48d
...
...
@@ -51,15 +51,22 @@ const (
var
(
// HTTPMETHOD list the supported http methods.
HTTPMETHOD
=
map
[
string
]
string
{
"GET"
:
"GET"
,
"POST"
:
"POST"
,
"PUT"
:
"PUT"
,
"DELETE"
:
"DELETE"
,
"PATCH"
:
"PATCH"
,
"OPTIONS"
:
"OPTIONS"
,
"HEAD"
:
"HEAD"
,
"TRACE"
:
"TRACE"
,
"CONNECT"
:
"CONNECT"
,
"GET"
:
"GET"
,
"POST"
:
"POST"
,
"PUT"
:
"PUT"
,
"DELETE"
:
"DELETE"
,
"PATCH"
:
"PATCH"
,
"OPTIONS"
:
"OPTIONS"
,
"HEAD"
:
"HEAD"
,
"TRACE"
:
"TRACE"
,
"CONNECT"
:
"CONNECT"
,
"MKCOL"
:
"MKCOL"
,
"COPY"
:
"COPY"
,
"MOVE"
:
"MOVE"
,
"PROPFIND"
:
"PROPFIND"
,
"PROPPATCH"
:
"PROPPATCH"
,
"LOCK"
:
"LOCK"
,
"UNLOCK"
:
"UNLOCK"
,
}
// these beego.Controller's methods shouldn't reflect to AutoRouter
exceptMethod
=
[]
string
{
"Init"
,
"Prepare"
,
"Finish"
,
"Render"
,
"RenderString"
,
...
...
session/mysql/sess_mysql.go
View file @
b235b48d
...
...
@@ -143,6 +143,7 @@ func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error {
// SessionRead get mysql session by sid
func
(
mp
*
Provider
)
SessionRead
(
sid
string
)
(
session
.
Store
,
error
)
{
c
:=
mp
.
connectInit
()
defer
c
.
Close
()
row
:=
c
.
QueryRow
(
"select session_data from "
+
TableName
+
" where session_key=?"
,
sid
)
var
sessiondata
[]
byte
err
:=
row
.
Scan
(
&
sessiondata
)
...
...
@@ -179,6 +180,7 @@ func (mp *Provider) SessionExist(sid string) bool {
// SessionRegenerate generate new sid for mysql session
func
(
mp
*
Provider
)
SessionRegenerate
(
oldsid
,
sid
string
)
(
session
.
Store
,
error
)
{
c
:=
mp
.
connectInit
()
defer
c
.
Close
()
row
:=
c
.
QueryRow
(
"select session_data from "
+
TableName
+
" where session_key=?"
,
oldsid
)
var
sessiondata
[]
byte
err
:=
row
.
Scan
(
&
sessiondata
)
...
...
session/sess_file.go
View file @
b235b48d
...
...
@@ -15,8 +15,7 @@
package
session
import
(
"errors"
"io"
"fmt"
"io/ioutil"
"net/http"
"os"
...
...
@@ -135,6 +134,9 @@ func (fp *FileProvider) SessionRead(sid string) (Store, error) {
}
else
{
return
nil
,
err
}
defer
f
.
Close
()
os
.
Chtimes
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
),
time
.
Now
(),
time
.
Now
())
var
kv
map
[
interface
{}]
interface
{}
b
,
err
:=
ioutil
.
ReadAll
(
f
)
...
...
@@ -149,7 +151,7 @@ func (fp *FileProvider) SessionRead(sid string) (Store, error) {
return
nil
,
err
}
}
f
.
Close
()
ss
:=
&
FileSessionStore
{
sid
:
sid
,
values
:
kv
}
return
ss
,
nil
}
...
...
@@ -204,49 +206,58 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
filepder
.
lock
.
Lock
()
defer
filepder
.
lock
.
Unlock
()
err
:=
os
.
MkdirAll
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
])),
0777
)
if
err
!=
nil
{
SLogger
.
Println
(
err
.
Error
())
oldPath
:=
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
]))
oldSidFile
:=
path
.
Join
(
oldPath
,
oldsid
)
newPath
:=
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]))
newSidFile
:=
path
.
Join
(
newPath
,
sid
)
// new sid file is exist
_
,
err
:=
os
.
Stat
(
newSidFile
)
if
err
==
nil
{
return
nil
,
fmt
.
Errorf
(
"newsid %s exist"
,
newSidFile
)
}
err
=
os
.
MkdirAll
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
])),
0777
)
err
=
os
.
MkdirAll
(
newPath
,
0777
)
if
err
!=
nil
{
SLogger
.
Println
(
err
.
Error
())
}
_
,
err
=
os
.
Stat
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
var
newf
*
os
.
File
if
err
==
nil
{
return
nil
,
errors
.
New
(
"newsid exist"
)
}
else
if
os
.
IsNotExist
(
err
)
{
newf
,
err
=
os
.
Create
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
}
_
,
err
=
os
.
Stat
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
]),
oldsid
))
var
f
*
os
.
File
// if old sid file exist
// 1.read and parse file content
// 2.write content to new sid file
// 3.remove old sid file, change new sid file atime and ctime
// 4.return FileSessionStore
_
,
err
=
os
.
Stat
(
oldSidFile
)
if
err
==
nil
{
f
,
err
=
os
.
OpenFile
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
]),
oldsid
),
os
.
O_RDWR
,
0777
)
io
.
Copy
(
newf
,
f
)
}
else
if
os
.
IsNotExist
(
err
)
{
newf
,
err
=
os
.
Create
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
))
}
else
{
return
nil
,
err
}
f
.
Close
()
os
.
Remove
(
path
.
Join
(
fp
.
savePath
,
string
(
oldsid
[
0
]),
string
(
oldsid
[
1
])))
os
.
Chtimes
(
path
.
Join
(
fp
.
savePath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
),
time
.
Now
(),
time
.
Now
())
var
kv
map
[
interface
{}]
interface
{}
b
,
err
:=
ioutil
.
ReadAll
(
newf
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
b
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
DecodeGob
(
b
)
b
,
err
:=
ioutil
.
ReadFile
(
oldSidFile
)
if
err
!=
nil
{
return
nil
,
err
}
var
kv
map
[
interface
{}]
interface
{}
if
len
(
b
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
DecodeGob
(
b
)
if
err
!=
nil
{
return
nil
,
err
}
}
ioutil
.
WriteFile
(
newSidFile
,
b
,
0777
)
os
.
Remove
(
oldSidFile
)
os
.
Chtimes
(
newSidFile
,
time
.
Now
(),
time
.
Now
())
ss
:=
&
FileSessionStore
{
sid
:
sid
,
values
:
kv
}
return
ss
,
nil
}
ss
:=
&
FileSessionStore
{
sid
:
sid
,
values
:
kv
}
// if old sid file not exist, just create new sid file and return
newf
,
err
:=
os
.
Create
(
newSidFile
)
if
err
!=
nil
{
return
nil
,
err
}
newf
.
Close
()
ss
:=
&
FileSessionStore
{
sid
:
sid
,
values
:
make
(
map
[
interface
{}]
interface
{})}
return
ss
,
nil
}
...
...
template.go
View file @
b235b48d
...
...
@@ -32,8 +32,9 @@ import (
var
(
beegoTplFuncMap
=
make
(
template
.
FuncMap
)
// beeTemplates caching map and supported template file extensions.
beeTemplates
=
make
(
map
[
string
]
*
template
.
Template
)
beeViewPathTemplateLocked
=
false
// beeViewPathTemplates caching map and supported template file extensions per view
beeViewPathTemplates
=
make
(
map
[
string
]
map
[
string
]
*
template
.
Template
)
templatesLock
sync
.
RWMutex
// beeTemplateExt stores the template extension which will build
beeTemplateExt
=
[]
string
{
"tpl"
,
"html"
}
...
...
@@ -45,23 +46,33 @@ var (
// writing the output to wr.
// A template will be executed safely in parallel.
func
ExecuteTemplate
(
wr
io
.
Writer
,
name
string
,
data
interface
{})
error
{
return
ExecuteViewPathTemplate
(
wr
,
name
,
BConfig
.
WebConfig
.
ViewsPath
,
data
)
}
// ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object,
// writing the output to wr.
// A template will be executed safely in parallel.
func
ExecuteViewPathTemplate
(
wr
io
.
Writer
,
name
string
,
viewPath
string
,
data
interface
{})
error
{
if
BConfig
.
RunMode
==
DEV
{
templatesLock
.
RLock
()
defer
templatesLock
.
RUnlock
()
}
if
t
,
ok
:=
beeTemplates
[
name
];
ok
{
var
err
error
if
t
.
Lookup
(
name
)
!=
nil
{
err
=
t
.
ExecuteTemplate
(
wr
,
name
,
data
)
}
else
{
err
=
t
.
Execute
(
wr
,
data
)
}
if
err
!=
nil
{
logs
.
Trace
(
"template Execute err:"
,
err
)
if
beeTemplates
,
ok
:=
beeViewPathTemplates
[
viewPath
];
ok
{
if
t
,
ok
:=
beeTemplates
[
name
];
ok
{
var
err
error
if
t
.
Lookup
(
name
)
!=
nil
{
err
=
t
.
ExecuteTemplate
(
wr
,
name
,
data
)
}
else
{
err
=
t
.
Execute
(
wr
,
data
)
}
if
err
!=
nil
{
logs
.
Trace
(
"template Execute err:"
,
err
)
}
return
err
}
return
err
panic
(
"can't find templatefile in the path:"
+
viewPath
+
"/"
+
name
)
}
panic
(
"
can't find templatefile in the path:"
+
name
)
panic
(
"
Uknown view path:"
+
viewPath
)
}
func
init
()
{
...
...
@@ -149,6 +160,21 @@ func AddTemplateExt(ext string) {
beeTemplateExt
=
append
(
beeTemplateExt
,
ext
)
}
// AddViewPath adds a new path to the supported view paths.
//Can later be used by setting a controller ViewPath to this folder
//will panic if called after beego.Run()
func
AddViewPath
(
viewPath
string
)
error
{
if
beeViewPathTemplateLocked
{
panic
(
"Can not add new view paths after beego.Run()"
)
}
beeViewPathTemplates
[
viewPath
]
=
make
(
map
[
string
]
*
template
.
Template
)
return
BuildTemplate
(
viewPath
)
}
func
lockViewPaths
()
{
beeViewPathTemplateLocked
=
true
}
// BuildTemplate will build all template files in a directory.
// it makes beego can render any template file in view directory.
func
BuildTemplate
(
dir
string
,
files
...
string
)
error
{
...
...
@@ -158,6 +184,10 @@ func BuildTemplate(dir string, files ...string) error {
}
return
errors
.
New
(
"dir open err"
)
}
beeTemplates
,
ok
:=
beeViewPathTemplates
[
dir
];
if
!
ok
{
panic
(
"Unknown view path: "
+
dir
)
}
self
:=
&
templateFile
{
root
:
dir
,
files
:
make
(
map
[
string
][]
string
),
...
...
@@ -224,7 +254,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
if
!
HasTemplateExt
(
m
[
1
])
{
continue
}
t
,
_
,
err
=
getTplDeep
(
root
,
m
[
1
],
file
,
t
)
_
,
_
,
err
=
getTplDeep
(
root
,
m
[
1
],
file
,
t
)
if
err
!=
nil
{
return
nil
,
[][]
string
{},
err
}
...
...
template_test.go
View file @
b235b48d
...
...
@@ -67,9 +67,10 @@ func TestTemplate(t *testing.T) {
f
.
Close
()
}
}
if
err
:=
BuildTemplate
(
dir
);
err
!=
nil
{
if
err
:=
AddViewPath
(
dir
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
beeTemplates
:=
beeViewPathTemplates
[
dir
]
if
len
(
beeTemplates
)
!=
3
{
t
.
Fatalf
(
"should be 3 but got %v"
,
len
(
beeTemplates
))
}
...
...
@@ -103,6 +104,12 @@ var user = `<!DOCTYPE html>
func
TestRelativeTemplate
(
t
*
testing
.
T
)
{
dir
:=
"_beeTmp"
//Just add dir to known viewPaths
if
err
:=
AddViewPath
(
dir
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
files
:=
[]
string
{
"easyui/public/menu.tpl"
,
"easyui/rbac/user.tpl"
,
...
...
@@ -126,6 +133,7 @@ func TestRelativeTemplate(t *testing.T) {
if
err
:=
BuildTemplate
(
dir
,
files
[
1
]);
err
!=
nil
{
t
.
Fatal
(
err
)
}
beeTemplates
:=
beeViewPathTemplates
[
dir
]
if
err
:=
beeTemplates
[
"easyui/rbac/user.tpl"
]
.
ExecuteTemplate
(
os
.
Stdout
,
"easyui/rbac/user.tpl"
,
nil
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment