Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
ef90f1dc
Commit
ef90f1dc
authored
Dec 30, 2014
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated readme
parent
aafe2c5b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
803 additions
and
45 deletions
+803
-45
Godeps/_workspace/src/github.com/macaron-contrib/session/file.go
+259
-0
Godeps/_workspace/src/github.com/macaron-contrib/session/file_test.go
+34
-0
Godeps/_workspace/src/github.com/macaron-contrib/session/memory.go
+212
-0
Godeps/_workspace/src/github.com/macaron-contrib/session/memory_test.go
+27
-0
Godeps/_workspace/src/github.com/macaron-contrib/session/session_test.go
+200
-0
Godeps/_workspace/src/github.com/macaron-contrib/session/utils.go
+69
-0
README.md
+2
-45
No files found.
Godeps/_workspace/src/github.com/macaron-contrib/session/file.go
0 → 100644
View file @
ef90f1dc
// Copyright 2013 Beego Authors
// Copyright 2014 Unknwon
//
// 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
session
import
(
"fmt"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"sync"
"time"
"github.com/Unknwon/com"
)
// FileSessionStore represents a file session store implementation.
type
FileSessionStore
struct
{
p
*
FileProvider
sid
string
lock
sync
.
RWMutex
data
map
[
interface
{}]
interface
{}
}
// NewFileSessionStore creates and returns a file session store.
func
NewFileSessionStore
(
p
*
FileProvider
,
sid
string
,
kv
map
[
interface
{}]
interface
{})
*
FileSessionStore
{
return
&
FileSessionStore
{
p
:
p
,
sid
:
sid
,
data
:
kv
,
}
}
// Set sets value to given key in session.
func
(
s
*
FileSessionStore
)
Set
(
key
,
val
interface
{})
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
s
.
data
[
key
]
=
val
return
nil
}
// Get gets value by given key in session.
func
(
s
*
FileSessionStore
)
Get
(
key
interface
{})
interface
{}
{
s
.
lock
.
RLock
()
defer
s
.
lock
.
RUnlock
()
return
s
.
data
[
key
]
}
// Delete delete a key from session.
func
(
s
*
FileSessionStore
)
Delete
(
key
interface
{})
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
delete
(
s
.
data
,
key
)
return
nil
}
// ID returns current session ID.
func
(
s
*
FileSessionStore
)
ID
()
string
{
return
s
.
sid
}
// Release releases resource and save data to provider.
func
(
s
*
FileSessionStore
)
Release
()
error
{
data
,
err
:=
EncodeGob
(
s
.
data
)
if
err
!=
nil
{
return
err
}
return
ioutil
.
WriteFile
(
s
.
p
.
filepath
(
s
.
sid
),
data
,
os
.
ModePerm
)
}
// Flush deletes all session data.
func
(
s
*
FileSessionStore
)
Flush
()
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
s
.
data
=
make
(
map
[
interface
{}]
interface
{})
return
nil
}
// FileProvider represents a file session provider implementation.
type
FileProvider
struct
{
lock
sync
.
RWMutex
maxlifetime
int64
rootPath
string
}
// Init initializes file session provider with given root path.
func
(
p
*
FileProvider
)
Init
(
maxlifetime
int64
,
rootPath
string
)
error
{
p
.
maxlifetime
=
maxlifetime
p
.
rootPath
=
rootPath
return
nil
}
func
(
p
*
FileProvider
)
filepath
(
sid
string
)
string
{
return
path
.
Join
(
p
.
rootPath
,
string
(
sid
[
0
]),
string
(
sid
[
1
]),
sid
)
}
// Read returns raw session store by session ID.
func
(
p
*
FileProvider
)
Read
(
sid
string
)
(
_
RawStore
,
err
error
)
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
filename
:=
p
.
filepath
(
sid
)
if
err
=
os
.
MkdirAll
(
path
.
Dir
(
filename
),
os
.
ModePerm
);
err
!=
nil
{
return
nil
,
err
}
var
f
*
os
.
File
if
com
.
IsFile
(
filename
)
{
f
,
err
=
os
.
OpenFile
(
filename
,
os
.
O_RDWR
,
os
.
ModePerm
)
}
else
{
f
,
err
=
os
.
Create
(
filename
)
}
if
err
!=
nil
{
return
nil
,
err
}
defer
f
.
Close
()
if
err
=
os
.
Chtimes
(
filename
,
time
.
Now
(),
time
.
Now
());
err
!=
nil
{
return
nil
,
err
}
var
kv
map
[
interface
{}]
interface
{}
data
,
err
:=
ioutil
.
ReadAll
(
f
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
data
)
==
0
{
kv
=
make
(
map
[
interface
{}]
interface
{})
}
else
{
kv
,
err
=
DecodeGob
(
data
)
if
err
!=
nil
{
return
nil
,
err
}
}
return
NewFileSessionStore
(
p
,
sid
,
kv
),
nil
}
// Exist returns true if session with given ID exists.
func
(
p
*
FileProvider
)
Exist
(
sid
string
)
bool
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
return
com
.
IsFile
(
p
.
filepath
(
sid
))
}
// Destory deletes a session by session ID.
func
(
p
*
FileProvider
)
Destory
(
sid
string
)
error
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
return
os
.
Remove
(
p
.
filepath
(
sid
))
}
func
(
p
*
FileProvider
)
regenerate
(
oldsid
,
sid
string
)
(
err
error
)
{
filename
:=
p
.
filepath
(
sid
)
if
com
.
IsExist
(
filename
)
{
return
fmt
.
Errorf
(
"new sid '%s' already exists"
,
sid
)
}
oldname
:=
p
.
filepath
(
oldsid
)
if
!
com
.
IsFile
(
oldname
)
{
data
,
err
:=
EncodeGob
(
make
(
map
[
interface
{}]
interface
{}))
if
err
!=
nil
{
return
err
}
if
err
=
os
.
MkdirAll
(
path
.
Dir
(
oldname
),
os
.
ModePerm
);
err
!=
nil
{
return
err
}
if
err
=
ioutil
.
WriteFile
(
oldname
,
data
,
os
.
ModePerm
);
err
!=
nil
{
return
err
}
}
if
err
=
os
.
MkdirAll
(
path
.
Dir
(
filename
),
os
.
ModePerm
);
err
!=
nil
{
return
err
}
if
err
=
os
.
Rename
(
oldname
,
filename
);
err
!=
nil
{
return
err
}
return
nil
}
// Regenerate regenerates a session store from old session ID to new one.
func
(
p
*
FileProvider
)
Regenerate
(
oldsid
,
sid
string
)
(
_
RawStore
,
err
error
)
{
p
.
lock
.
Lock
()
if
err
:=
p
.
regenerate
(
oldsid
,
sid
);
err
!=
nil
{
p
.
lock
.
Unlock
()
return
nil
,
err
}
p
.
lock
.
Unlock
()
return
p
.
Read
(
sid
)
}
// Count counts and returns number of sessions.
func
(
p
*
FileProvider
)
Count
()
int
{
count
:=
0
if
err
:=
filepath
.
Walk
(
p
.
rootPath
,
func
(
path
string
,
fi
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
return
err
}
if
!
fi
.
IsDir
()
{
count
++
}
return
nil
});
err
!=
nil
{
log
.
Printf
(
"error counting session files: %v"
,
err
)
return
0
}
return
count
}
// GC calls GC to clean expired sessions.
func
(
p
*
FileProvider
)
GC
()
{
if
!
com
.
IsExist
(
p
.
rootPath
)
{
return
}
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
if
err
:=
filepath
.
Walk
(
p
.
rootPath
,
func
(
path
string
,
fi
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
return
err
}
if
!
fi
.
IsDir
()
&&
(
fi
.
ModTime
()
.
Unix
()
+
p
.
maxlifetime
)
<
time
.
Now
()
.
Unix
()
{
return
os
.
Remove
(
path
)
}
return
nil
});
err
!=
nil
{
log
.
Printf
(
"error garbage collecting session files: %v"
,
err
)
}
}
func
init
()
{
Register
(
"file"
,
&
FileProvider
{})
}
Godeps/_workspace/src/github.com/macaron-contrib/session/file_test.go
0 → 100644
View file @
ef90f1dc
// Copyright 2014 Unknwon
//
// 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
session
import
(
"os"
"path"
"testing"
.
"github.com/smartystreets/goconvey/convey"
)
func
Test_FileProvider
(
t
*
testing
.
T
)
{
Convey
(
"Test file session provider"
,
t
,
func
()
{
dir
:=
path
.
Join
(
os
.
TempDir
(),
"data/sessions"
)
os
.
RemoveAll
(
dir
)
testProvider
(
Options
{
Provider
:
"file"
,
ProviderConfig
:
dir
,
})
})
}
Godeps/_workspace/src/github.com/macaron-contrib/session/memory.go
0 → 100644
View file @
ef90f1dc
// Copyright 2013 Beego Authors
// Copyright 2014 Unknwon
//
// 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
session
import
(
"container/list"
"fmt"
"sync"
"time"
)
// MemSessionStore represents a in-memory session store implementation.
type
MemSessionStore
struct
{
sid
string
lock
sync
.
RWMutex
data
map
[
interface
{}]
interface
{}
lastAccess
time
.
Time
}
// NewMemSessionStore creates and returns a memory session store.
func
NewMemSessionStore
(
sid
string
)
*
MemSessionStore
{
return
&
MemSessionStore
{
sid
:
sid
,
data
:
make
(
map
[
interface
{}]
interface
{}),
lastAccess
:
time
.
Now
(),
}
}
// Set sets value to given key in session.
func
(
s
*
MemSessionStore
)
Set
(
key
,
val
interface
{})
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
s
.
data
[
key
]
=
val
return
nil
}
// Get gets value by given key in session.
func
(
s
*
MemSessionStore
)
Get
(
key
interface
{})
interface
{}
{
s
.
lock
.
RLock
()
defer
s
.
lock
.
RUnlock
()
return
s
.
data
[
key
]
}
// Delete delete a key from session.
func
(
s
*
MemSessionStore
)
Delete
(
key
interface
{})
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
delete
(
s
.
data
,
key
)
return
nil
}
// ID returns current session ID.
func
(
s
*
MemSessionStore
)
ID
()
string
{
return
s
.
sid
}
// Release releases resource and save data to provider.
func
(
_
*
MemSessionStore
)
Release
()
error
{
return
nil
}
// Flush deletes all session data.
func
(
s
*
MemSessionStore
)
Flush
()
error
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
s
.
data
=
make
(
map
[
interface
{}]
interface
{})
return
nil
}
// MemProvider represents a in-memory session provider implementation.
type
MemProvider
struct
{
lock
sync
.
RWMutex
maxLifetime
int64
data
map
[
string
]
*
list
.
Element
// A priority list whose lastAccess newer gets higer priority.
list
*
list
.
List
}
// Init initializes memory session provider.
func
(
p
*
MemProvider
)
Init
(
maxLifetime
int64
,
_
string
)
error
{
p
.
maxLifetime
=
maxLifetime
return
nil
}
// update expands time of session store by given ID.
func
(
p
*
MemProvider
)
update
(
sid
string
)
error
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
if
e
,
ok
:=
p
.
data
[
sid
];
ok
{
e
.
Value
.
(
*
MemSessionStore
)
.
lastAccess
=
time
.
Now
()
p
.
list
.
MoveToFront
(
e
)
return
nil
}
return
nil
}
// Read returns raw session store by session ID.
func
(
p
*
MemProvider
)
Read
(
sid
string
)
(
_
RawStore
,
err
error
)
{
p
.
lock
.
RLock
()
e
,
ok
:=
p
.
data
[
sid
]
p
.
lock
.
RUnlock
()
if
ok
{
if
err
=
p
.
update
(
sid
);
err
!=
nil
{
return
nil
,
err
}
return
e
.
Value
.
(
*
MemSessionStore
),
nil
}
// Create a new session.
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
s
:=
NewMemSessionStore
(
sid
)
p
.
data
[
sid
]
=
p
.
list
.
PushBack
(
s
)
return
s
,
nil
}
// Exist returns true if session with given ID exists.
func
(
p
*
MemProvider
)
Exist
(
sid
string
)
bool
{
p
.
lock
.
RLock
()
defer
p
.
lock
.
RUnlock
()
_
,
ok
:=
p
.
data
[
sid
]
return
ok
}
// Destory deletes a session by session ID.
func
(
p
*
MemProvider
)
Destory
(
sid
string
)
error
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
e
,
ok
:=
p
.
data
[
sid
]
if
!
ok
{
return
nil
}
p
.
list
.
Remove
(
e
)
delete
(
p
.
data
,
sid
)
return
nil
}
// Regenerate regenerates a session store from old session ID to new one.
func
(
p
*
MemProvider
)
Regenerate
(
oldsid
,
sid
string
)
(
RawStore
,
error
)
{
if
p
.
Exist
(
sid
)
{
return
nil
,
fmt
.
Errorf
(
"new sid '%s' already exists"
,
sid
)
}
s
,
err
:=
p
.
Read
(
oldsid
)
if
err
!=
nil
{
return
nil
,
err
}
if
err
=
p
.
Destory
(
oldsid
);
err
!=
nil
{
return
nil
,
err
}
s
.
(
*
MemSessionStore
)
.
sid
=
sid
p
.
data
[
sid
]
=
p
.
list
.
PushBack
(
s
)
return
s
,
nil
}
// Count counts and returns number of sessions.
func
(
p
*
MemProvider
)
Count
()
int
{
return
p
.
list
.
Len
()
}
// GC calls GC to clean expired sessions.
func
(
p
*
MemProvider
)
GC
()
{
p
.
lock
.
RLock
()
for
{
// No session in the list.
e
:=
p
.
list
.
Back
()
if
e
==
nil
{
break
}
if
(
e
.
Value
.
(
*
MemSessionStore
)
.
lastAccess
.
Unix
()
+
p
.
maxLifetime
)
<
time
.
Now
()
.
Unix
()
{
p
.
lock
.
RUnlock
()
p
.
lock
.
Lock
()
p
.
list
.
Remove
(
e
)
delete
(
p
.
data
,
e
.
Value
.
(
*
MemSessionStore
)
.
sid
)
p
.
lock
.
Unlock
()
p
.
lock
.
RLock
()
}
else
{
break
}
}
p
.
lock
.
RUnlock
()
}
func
init
()
{
Register
(
"memory"
,
&
MemProvider
{
list
:
list
.
New
(),
data
:
make
(
map
[
string
]
*
list
.
Element
)})
}
Godeps/_workspace/src/github.com/macaron-contrib/session/memory_test.go
0 → 100644
View file @
ef90f1dc
// Copyright 2014 Unknwon
//
// 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
session
import
(
"testing"
.
"github.com/smartystreets/goconvey/convey"
)
func
Test_MemProvider
(
t
*
testing
.
T
)
{
Convey
(
"Test memory session provider"
,
t
,
func
()
{
testProvider
(
Options
{})
})
}
Godeps/_workspace/src/github.com/macaron-contrib/session/session_test.go
0 → 100644
View file @
ef90f1dc
// Copyright 2014 Unknwon
//
// 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
session
import
(
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/Unknwon/macaron"
.
"github.com/smartystreets/goconvey/convey"
)
func
Test_Version
(
t
*
testing
.
T
)
{
Convey
(
"Check package version"
,
t
,
func
()
{
So
(
Version
(),
ShouldEqual
,
_VERSION
)
})
}
func
Test_Sessioner
(
t
*
testing
.
T
)
{
Convey
(
"Use session middleware"
,
t
,
func
()
{
m
:=
macaron
.
New
()
m
.
Use
(
Sessioner
())
m
.
Get
(
"/"
,
func
()
{})
resp
:=
httptest
.
NewRecorder
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/"
,
nil
)
So
(
err
,
ShouldBeNil
)
m
.
ServeHTTP
(
resp
,
req
)
})
Convey
(
"Register invalid provider that"
,
t
,
func
()
{
Convey
(
"Provider not exists"
,
func
()
{
defer
func
()
{
So
(
recover
(),
ShouldNotBeNil
)
}()
m
:=
macaron
.
New
()
m
.
Use
(
Sessioner
(
Options
{
Provider
:
"fake"
,
}))
})
Convey
(
"Provider value is nil"
,
func
()
{
defer
func
()
{
So
(
recover
(),
ShouldNotBeNil
)
}()
Register
(
"fake"
,
nil
)
})
Convey
(
"Register twice"
,
func
()
{
defer
func
()
{
So
(
recover
(),
ShouldNotBeNil
)
}()
Register
(
"memory"
,
&
MemProvider
{})
})
})
}
func
testProvider
(
opt
Options
)
{
Convey
(
"Basic operation"
,
func
()
{
m
:=
macaron
.
New
()
m
.
Use
(
Sessioner
(
opt
))
m
.
Get
(
"/"
,
func
(
ctx
*
macaron
.
Context
,
sess
Store
)
{
sess
.
Set
(
"uname"
,
"unknwon"
)
})
m
.
Get
(
"/reg"
,
func
(
ctx
*
macaron
.
Context
,
sess
Store
)
{
raw
,
err
:=
sess
.
RegenerateId
(
ctx
)
So
(
err
,
ShouldBeNil
)
So
(
raw
,
ShouldNotBeNil
)
uname
:=
raw
.
Get
(
"uname"
)
So
(
uname
,
ShouldNotBeNil
)
So
(
uname
,
ShouldEqual
,
"unknwon"
)
})
m
.
Get
(
"/get"
,
func
(
ctx
*
macaron
.
Context
,
sess
Store
)
{
sid
:=
sess
.
ID
()
So
(
sid
,
ShouldNotBeEmpty
)
raw
,
err
:=
sess
.
Read
(
sid
)
So
(
err
,
ShouldBeNil
)
So
(
raw
,
ShouldNotBeNil
)
uname
:=
sess
.
Get
(
"uname"
)
So
(
uname
,
ShouldNotBeNil
)
So
(
uname
,
ShouldEqual
,
"unknwon"
)
So
(
sess
.
Delete
(
"uname"
),
ShouldBeNil
)
So
(
sess
.
Get
(
"uname"
),
ShouldBeNil
)
So
(
sess
.
Destory
(
ctx
),
ShouldBeNil
)
})
resp
:=
httptest
.
NewRecorder
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/"
,
nil
)
So
(
err
,
ShouldBeNil
)
m
.
ServeHTTP
(
resp
,
req
)
cookie
:=
resp
.
Header
()
.
Get
(
"Set-Cookie"
)
resp
=
httptest
.
NewRecorder
()
req
,
err
=
http
.
NewRequest
(
"GET"
,
"/reg"
,
nil
)
So
(
err
,
ShouldBeNil
)
req
.
Header
.
Set
(
"Cookie"
,
cookie
)
m
.
ServeHTTP
(
resp
,
req
)
cookie
=
resp
.
Header
()
.
Get
(
"Set-Cookie"
)
resp
=
httptest
.
NewRecorder
()
req
,
err
=
http
.
NewRequest
(
"GET"
,
"/get"
,
nil
)
So
(
err
,
ShouldBeNil
)
req
.
Header
.
Set
(
"Cookie"
,
cookie
)
m
.
ServeHTTP
(
resp
,
req
)
})
Convey
(
"Regenrate empty session"
,
func
()
{
m
:=
macaron
.
New
()
m
.
Use
(
Sessioner
(
opt
))
m
.
Get
(
"/"
,
func
(
ctx
*
macaron
.
Context
,
sess
Store
)
{
raw
,
err
:=
sess
.
RegenerateId
(
ctx
)
So
(
err
,
ShouldBeNil
)
So
(
raw
,
ShouldNotBeNil
)
})
resp
:=
httptest
.
NewRecorder
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/"
,
nil
)
So
(
err
,
ShouldBeNil
)
req
.
Header
.
Set
(
"Cookie"
,
"MacaronSession=ad2c7e3cbecfcf486; Path=/;"
)
m
.
ServeHTTP
(
resp
,
req
)
})
Convey
(
"GC session"
,
func
()
{
m
:=
macaron
.
New
()
opt2
:=
opt
opt2
.
Gclifetime
=
1
m
.
Use
(
Sessioner
(
opt2
))
m
.
Get
(
"/"
,
func
(
sess
Store
)
{
sess
.
Set
(
"uname"
,
"unknwon"
)
So
(
sess
.
ID
(),
ShouldNotBeEmpty
)
uname
:=
sess
.
Get
(
"uname"
)
So
(
uname
,
ShouldNotBeNil
)
So
(
uname
,
ShouldEqual
,
"unknwon"
)
So
(
sess
.
Flush
(),
ShouldBeNil
)
So
(
sess
.
Get
(
"uname"
),
ShouldBeNil
)
time
.
Sleep
(
2
*
time
.
Second
)
sess
.
GC
()
So
(
sess
.
Count
(),
ShouldEqual
,
0
)
})
resp
:=
httptest
.
NewRecorder
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/"
,
nil
)
So
(
err
,
ShouldBeNil
)
m
.
ServeHTTP
(
resp
,
req
)
})
}
func
Test_Flash
(
t
*
testing
.
T
)
{
Convey
(
"Test flash"
,
t
,
func
()
{
m
:=
macaron
.
New
()
m
.
Use
(
Sessioner
())
m
.
Get
(
"/set"
,
func
(
f
*
Flash
)
string
{
f
.
Success
(
"success"
)
f
.
Error
(
"error"
)
f
.
Warning
(
"warning"
)
f
.
Info
(
"info"
)
return
""
})
m
.
Get
(
"/get"
,
func
()
{})
resp
:=
httptest
.
NewRecorder
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/set"
,
nil
)
So
(
err
,
ShouldBeNil
)
m
.
ServeHTTP
(
resp
,
req
)
resp
=
httptest
.
NewRecorder
()
req
,
err
=
http
.
NewRequest
(
"GET"
,
"/get"
,
nil
)
So
(
err
,
ShouldBeNil
)
req
.
Header
.
Set
(
"Cookie"
,
"macaron_flash=error%3Derror%26info%3Dinfo%26success%3Dsuccess%26warning%3Dwarning; Path=/"
)
m
.
ServeHTTP
(
resp
,
req
)
})
}
Godeps/_workspace/src/github.com/macaron-contrib/session/utils.go
0 → 100644
View file @
ef90f1dc
// Copyright 2013 Beego Authors
// Copyright 2014 Unknwon
//
// 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
session
import
(
"bytes"
"crypto/rand"
"encoding/gob"
"io"
"github.com/Unknwon/com"
)
func
init
()
{
gob
.
Register
([]
interface
{}{})
gob
.
Register
(
map
[
int
]
interface
{}{})
gob
.
Register
(
map
[
string
]
interface
{}{})
gob
.
Register
(
map
[
interface
{}]
interface
{}{})
gob
.
Register
(
map
[
string
]
string
{})
gob
.
Register
(
map
[
int
]
string
{})
gob
.
Register
(
map
[
int
]
int
{})
gob
.
Register
(
map
[
int
]
int64
{})
}
func
EncodeGob
(
obj
map
[
interface
{}]
interface
{})
([]
byte
,
error
)
{
for
_
,
v
:=
range
obj
{
gob
.
Register
(
v
)
}
buf
:=
bytes
.
NewBuffer
(
nil
)
enc
:=
gob
.
NewEncoder
(
buf
)
err
:=
enc
.
Encode
(
obj
)
if
err
!=
nil
{
return
[]
byte
(
""
),
err
}
return
buf
.
Bytes
(),
nil
}
func
DecodeGob
(
encoded
[]
byte
)
(
map
[
interface
{}]
interface
{},
error
)
{
buf
:=
bytes
.
NewBuffer
(
encoded
)
dec
:=
gob
.
NewDecoder
(
buf
)
var
out
map
[
interface
{}]
interface
{}
err
:=
dec
.
Decode
(
&
out
)
if
err
!=
nil
{
return
nil
,
err
}
return
out
,
nil
}
// generateRandomKey creates a random key with the given strength.
func
generateRandomKey
(
strength
int
)
[]
byte
{
k
:=
make
([]
byte
,
strength
)
if
n
,
err
:=
io
.
ReadFull
(
rand
.
Reader
,
k
);
n
!=
strength
||
err
!=
nil
{
return
com
.
RandomCreateBytes
(
strength
)
}
return
k
}
README.md
View file @
ef90f1dc
grafana-pro
===========
This is very much a Work in Progess. The architecture and organisation has changed many times and I am not very happy
with the current structure and architecture. I started with a lot of unit tests and drove the design though that in
the begining, but then having changed the code and structure (and web framework libs, and database) I sort of
abandoned them. When the architecture is getting more stable I will write & require more unit & integration tests.
# Architecture
I have researched a lot of go projects, found very few with a nice modular & loosly coupled archictecture. Go projects
organize code very differently, some treat packages as global singletons (which reads nicely and is nice to work with
but seems like a bad practice). I do miss generics for doing strongly typed but loosley coupled command/query style
internal buss messaging.
The biggest challange for architecture is making Grafana Pro very modular in a way that all/most components can
run inproc or in seperate process (usefull when running Grafana Pro in a large scale SaaS setup). Been investigating
using ZeroMQ or NanoMsg to handle module communication (Both ZeroMQ and NanoMsg can handle inproc & tcp which a number of
different topologies). Running Grafana Pro in a SaaS setup might warrant that the alerting stuff runs out of proc on
other servers feeding of a queue for example, but for simple on prem stuff it would be cool if that could be run in the
same process. I am also thinking that some stuff might need swapping out/in depending on the setup (plugin model or just
interfaces with different implementations).
# Building
*
Just added a simple make file (the main binary package is in pkg/cmd/grafana-pro)
*
Need to change to godep or some go lang dependency management system
# Data access
Data access is very strange right now, instead of an interface I tried using public methods in the models package.
These method pointers are assigned in when the sqlstore is initialized in pkg/store/sqlstore. This is probably a
bad idea. I am thinking about either moving to simple interfaces. But I do not want a giant interface for all
data acess. Would much prefe a simple generic command/query interface but golang lacks generics which makes this
painful. But a generic command/query interface could still be good as it would make it easier to have some commands or
queries handled buy out of proc components (or inproc if we used someting like ZeroMQ for communication). Or it
could be overengineering thinking like this.
# Grafana frontend
The grafana frontend is added as git submodule in order to easily sync with upstream grafana.
There should be a symbolic link from ./grafana/src to ./public . Need to add this to the Makefile.
# TODO
*
Add symbolik link between ./grafana/src ./public
*
Hash & Salt password
*
Unit tests for data access
*
I switched recently from rethinkdb to sql (using a simple mini ORM lib called xorm, might need to switch to a more
popular ORM lib).
Work in progress Grafana 2.0 (with included Grafana backend)
[
![wercker status
](
https://app.wercker.com/status/0f109051cfaf2a6d94c0eebdc0dcaeae/s
"wercker status"
)
](https://app.wercker.com/project/bykey/0f109051cfaf2a6d94c0eebdc0dcaeae)
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