summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lafriks/xormstore
diff options
context:
space:
mode:
authorLauris BH <lauris@nix.lv>2018-04-29 09:09:24 +0300
committerGitHub <noreply@github.com>2018-04-29 09:09:24 +0300
commit5a62eb30df3a04e76e465824f525b4ffd920b562 (patch)
treec3410d159a14a6b6d36b2ffadebbfb7dd48617f9 /vendor/github.com/lafriks/xormstore
parent8d5f58d8347196fca04fdf3a22d021d09d15e37f (diff)
downloadgitea-5a62eb30df3a04e76e465824f525b4ffd920b562.tar.gz
gitea-5a62eb30df3a04e76e465824f525b4ffd920b562.zip
Store OAuth2 session data in database (#3660)
* Store OAuth2 session data in database * Rename table to `oauth2_session` and do not skip xormstorage initialization error
Diffstat (limited to 'vendor/github.com/lafriks/xormstore')
-rw-r--r--vendor/github.com/lafriks/xormstore/Gopkg.lock75
-rw-r--r--vendor/github.com/lafriks/xormstore/Gopkg.toml50
-rw-r--r--vendor/github.com/lafriks/xormstore/LICENSE19
-rw-r--r--vendor/github.com/lafriks/xormstore/README.md48
-rwxr-xr-xvendor/github.com/lafriks/xormstore/test70
-rw-r--r--vendor/github.com/lafriks/xormstore/util/time_stamp.go60
-rw-r--r--vendor/github.com/lafriks/xormstore/xormstore.go251
7 files changed, 573 insertions, 0 deletions
diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.lock b/vendor/github.com/lafriks/xormstore/Gopkg.lock
new file mode 100644
index 0000000000..0d2cf03cba
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/Gopkg.lock
@@ -0,0 +1,75 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ branch = "master"
+ name = "github.com/denisenkom/go-mssqldb"
+ packages = ["."]
+ revision = "ee492709d4324cdcb051d2ac266b77ddc380f5c5"
+
+[[projects]]
+ name = "github.com/go-sql-driver/mysql"
+ packages = ["."]
+ revision = "a0583e0143b1624142adab07e0e97fe106d99561"
+ version = "v1.3"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/go-xorm/builder"
+ packages = ["."]
+ revision = "488224409dd8aa2ce7a5baf8d10d55764a913738"
+
+[[projects]]
+ name = "github.com/go-xorm/core"
+ packages = ["."]
+ revision = "da1adaf7a28ca792961721a34e6e04945200c890"
+ version = "v0.5.7"
+
+[[projects]]
+ name = "github.com/go-xorm/xorm"
+ packages = ["."]
+ revision = "1933dd69e294c0a26c0266637067f24dbb25770c"
+ version = "v0.6.4"
+
+[[projects]]
+ name = "github.com/gorilla/context"
+ packages = ["."]
+ revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
+ version = "v1.1"
+
+[[projects]]
+ name = "github.com/gorilla/securecookie"
+ packages = ["."]
+ revision = "e59506cc896acb7f7bf732d4fdf5e25f7ccd8983"
+ version = "v1.1.1"
+
+[[projects]]
+ name = "github.com/gorilla/sessions"
+ packages = ["."]
+ revision = "ca9ada44574153444b00d3fd9c8559e4cc95f896"
+ version = "v1.1"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/lib/pq"
+ packages = [".","oid"]
+ revision = "88edab0803230a3898347e77b474f8c1820a1f20"
+
+[[projects]]
+ name = "github.com/mattn/go-sqlite3"
+ packages = ["."]
+ revision = "6c771bb9887719704b210e87e934f08be014bdb1"
+ version = "v1.6.0"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/crypto"
+ packages = ["md4"]
+ revision = "c7dcf104e3a7a1417abc0230cb0d5240d764159d"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "bba98a94e8c6668ae9556b4978bbffdfc5d4d535d522c8865465335bfaa2fc70"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/vendor/github.com/lafriks/xormstore/Gopkg.toml b/vendor/github.com/lafriks/xormstore/Gopkg.toml
new file mode 100644
index 0000000000..ea71d50eaf
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/Gopkg.toml
@@ -0,0 +1,50 @@
+
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+
+
+[[constraint]]
+ name = "github.com/go-sql-driver/mysql"
+ version = "1.3.0"
+
+[[constraint]]
+ name = "github.com/go-xorm/xorm"
+ version = "0.6.4"
+
+[[constraint]]
+ name = "github.com/gorilla/context"
+ version = "1.1.0"
+
+[[constraint]]
+ name = "github.com/gorilla/securecookie"
+ version = "1.1.1"
+
+[[constraint]]
+ name = "github.com/gorilla/sessions"
+ version = "1.1.0"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/lib/pq"
+
+[[constraint]]
+ name = "github.com/mattn/go-sqlite3"
+ version = "1.6.0"
diff --git a/vendor/github.com/lafriks/xormstore/LICENSE b/vendor/github.com/lafriks/xormstore/LICENSE
new file mode 100644
index 0000000000..7a2dab6c17
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018 Lauris Bukšis-Haberkorns, Mattias Wadman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/lafriks/xormstore/README.md b/vendor/github.com/lafriks/xormstore/README.md
new file mode 100644
index 0000000000..361c5871fc
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/README.md
@@ -0,0 +1,48 @@
+[![GoDoc](https://godoc.org/github.com/lafriks/xormstore?status.svg)](https://godoc.org/github.com/lafriks/xormstore)
+[![Build Status](https://travis-ci.org/lafriks/xormstore.svg?branch=master)](https://travis-ci.org/lafriks/xormstore)
+[![codecov](https://codecov.io/gh/lafriks/xormstore/branch/master/graph/badge.svg)](https://codecov.io/gh/lafriks/xormstore)
+
+#### XORM backend for gorilla sessions
+
+ go get github.com/lafriks/xormstore
+
+#### Example
+
+```go
+// initialize and setup cleanup
+store := xormstore.New(engine, []byte("secret"))
+// db cleanup every hour
+// close quit channel to stop cleanup
+quit := make(chan struct{})
+go store.PeriodicCleanup(1*time.Hour, quit)
+```
+
+```go
+// in HTTP handler
+func handlerFunc(w http.ResponseWriter, r *http.Request) {
+ session, err := store.Get(r, "session")
+ session.Values["user_id"] = 123
+ store.Save(r, w, session)
+ http.Error(w, "", http.StatusOK)
+}
+```
+
+For more details see [xormstore godoc documentation](https://godoc.org/github.com/lafriks/xormstore).
+
+#### Testing
+
+Just sqlite3 tests:
+
+ go test
+
+All databases using docker:
+
+ ./test
+
+If docker is not local (docker-machine etc):
+
+ DOCKER_IP=$(docker-machine ip dev) ./test
+
+#### License
+
+xormstore is licensed under the MIT license. See [LICENSE](LICENSE) for the full license text.
diff --git a/vendor/github.com/lafriks/xormstore/test b/vendor/github.com/lafriks/xormstore/test
new file mode 100755
index 0000000000..4b06eae4e7
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/test
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+DOCKER_IP=${DOCKER_IP:-127.0.0.1}
+
+sqlite3() {
+ DATABASE_URI="sqlite3://file:dummy?mode=memory&cache=shared" go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic
+ return $?
+}
+
+postgres10() {
+ ID=$(docker run -p 5432 -d postgres:10-alpine)
+ PORT=$(docker port "$ID" 5432 | cut -d : -f 2)
+ DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover
+ S=$?
+ docker rm -vf "$ID" > /dev/null
+ return $S
+}
+
+postgres96() {
+ ID=$(docker run -p 5432 -d postgres:9.6-alpine)
+ PORT=$(docker port "$ID" 5432 | cut -d : -f 2)
+ DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover
+ S=$?
+ docker rm -vf "$ID" > /dev/null
+ return $S
+}
+
+postgres94() {
+ ID=$(docker run -p 5432 -d postgres:9.4-alpine)
+ PORT=$(docker port "$ID" 5432 | cut -d : -f 2)
+ DATABASE_URI="postgres://user=postgres password=postgres dbname=postgres host=$DOCKER_IP port=$PORT sslmode=disable" go test -v -race -cover
+ S=$?
+ docker rm -vf "$ID" > /dev/null
+ return $S
+}
+
+mysql57() {
+ ID=$(docker run \
+ -e MYSQL_ROOT_PASSWORD=root \
+ -e MYSQL_USER=mysql \
+ -e MYSQL_PASSWORD=mysql \
+ -e MYSQL_DATABASE=mysql \
+ -p 3306 -d mysql:5.7)
+ PORT=$(docker port "$ID" 3306 | cut -d : -f 2)
+ DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover
+ S=$?
+ docker rm -vf "$ID" > /dev/null
+ return $S
+}
+
+mariadb10() {
+ ID=$(docker run \
+ -e MYSQL_ROOT_PASSWORD=root \
+ -e MYSQL_USER=mysql \
+ -e MYSQL_PASSWORD=mysql \
+ -e MYSQL_DATABASE=mysql \
+ -p 3306 -d mariadb:10)
+ PORT=$(docker port "$ID" 3306 | cut -d : -f 2)
+ DATABASE_URI="mysql://mysql:mysql@tcp($DOCKER_IP:$PORT)/mysql?charset=utf8&parseTime=True" go test -v -race -cover
+ S=$?
+ docker rm -vf "$ID" > /dev/null
+ return $S
+}
+
+sqlite3 || exit 1
+postgres94 || exit 1
+postgres96 || exit 1
+postgres10 || exit 1
+mysql57 || exit 1
+mariadb10 || exit 1
diff --git a/vendor/github.com/lafriks/xormstore/util/time_stamp.go b/vendor/github.com/lafriks/xormstore/util/time_stamp.go
new file mode 100644
index 0000000000..2036fdf2f1
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/util/time_stamp.go
@@ -0,0 +1,60 @@
+package util
+
+import (
+ "time"
+)
+
+// TimeStamp defines a timestamp
+type TimeStamp int64
+
+// TimeStampNow returns now int64
+func TimeStampNow() TimeStamp {
+ return TimeStamp(time.Now().Unix())
+}
+
+// Add adds seconds and return sum
+func (ts TimeStamp) Add(seconds int64) TimeStamp {
+ return ts + TimeStamp(seconds)
+}
+
+// AddDuration adds time.Duration and return sum
+func (ts TimeStamp) AddDuration(interval time.Duration) TimeStamp {
+ return ts + TimeStamp(interval/time.Second)
+}
+
+// Year returns the time's year
+func (ts TimeStamp) Year() int {
+ return ts.AsTime().Year()
+}
+
+// AsTime convert timestamp as time.Time in Local locale
+func (ts TimeStamp) AsTime() (tm time.Time) {
+ tm = time.Unix(int64(ts), 0).Local()
+ return
+}
+
+// AsTimePtr convert timestamp as *time.Time in Local locale
+func (ts TimeStamp) AsTimePtr() *time.Time {
+ tm := time.Unix(int64(ts), 0).Local()
+ return &tm
+}
+
+// Format formats timestamp as
+func (ts TimeStamp) Format(f string) string {
+ return ts.AsTime().Format(f)
+}
+
+// FormatLong formats as RFC1123Z
+func (ts TimeStamp) FormatLong() string {
+ return ts.Format(time.RFC1123Z)
+}
+
+// FormatShort formats as short
+func (ts TimeStamp) FormatShort() string {
+ return ts.Format("Jan 02, 2006")
+}
+
+// IsZero is zero time
+func (ts TimeStamp) IsZero() bool {
+ return ts.AsTime().IsZero()
+}
diff --git a/vendor/github.com/lafriks/xormstore/xormstore.go b/vendor/github.com/lafriks/xormstore/xormstore.go
new file mode 100644
index 0000000000..f73db2e273
--- /dev/null
+++ b/vendor/github.com/lafriks/xormstore/xormstore.go
@@ -0,0 +1,251 @@
+/*
+Package xormstore is a XORM backend for gorilla sessions
+
+Simplest form:
+
+ store, err := xormstore.New(engine, []byte("secret-hash-key"))
+
+All options:
+
+ store, err := xormstore.NewOptions(
+ engine, // *xorm.Engine
+ xormstore.Options{
+ TableName: "sessions", // "sessions" is default
+ SkipCreateTable: false, // false is default
+ },
+ []byte("secret-hash-key"), // 32 or 64 bytes recommended, required
+ []byte("secret-encyption-key")) // nil, 16, 24 or 32 bytes, optional
+
+ if err != nil {
+ // xormstore can not be initialized
+ }
+
+ // some more settings, see sessions.Options
+ store.SessionOpts.Secure = true
+ store.SessionOpts.HttpOnly = true
+ store.SessionOpts.MaxAge = 60 * 60 * 24 * 60
+
+If you want periodic cleanup of expired sessions:
+
+ quit := make(chan struct{})
+ go store.PeriodicCleanup(1*time.Hour, quit)
+
+For more information about the keys see https://github.com/gorilla/securecookie
+
+For API to use in HTTP handlers see https://github.com/gorilla/sessions
+*/
+package xormstore
+
+import (
+ "encoding/base32"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/lafriks/xormstore/util"
+
+ "github.com/go-xorm/xorm"
+ "github.com/gorilla/context"
+ "github.com/gorilla/securecookie"
+ "github.com/gorilla/sessions"
+)
+
+const sessionIDLen = 32
+const defaultTableName = "sessions"
+const defaultMaxAge = 60 * 60 * 24 * 30 // 30 days
+const defaultPath = "/"
+
+// Options for xormstore
+type Options struct {
+ TableName string
+ SkipCreateTable bool
+}
+
+// Store represent a xormstore
+type Store struct {
+ e *xorm.Engine
+ opts Options
+ Codecs []securecookie.Codec
+ SessionOpts *sessions.Options
+}
+
+type xormSession struct {
+ ID string `xorm:"VARCHAR(400) PK NAME 'id'"`
+ Data string `xorm:"TEXT"`
+ CreatedUnix util.TimeStamp `xorm:"created"`
+ UpdatedUnix util.TimeStamp `xorm:"updated"`
+ ExpiresUnix util.TimeStamp `xorm:"INDEX"`
+
+ tableName string `xorm:"-"` // just to store table name for easier access
+}
+
+// Define a type for context keys so that they can't clash with anything else stored in context
+type contextKey string
+
+func (xs *xormSession) TableName() string {
+ return xs.tableName
+}
+
+// New creates a new xormstore session
+func New(e *xorm.Engine, keyPairs ...[]byte) (*Store, error) {
+ return NewOptions(e, Options{}, keyPairs...)
+}
+
+// NewOptions creates a new xormstore session with options
+func NewOptions(e *xorm.Engine, opts Options, keyPairs ...[]byte) (*Store, error) {
+ st := &Store{
+ e: e,
+ opts: opts,
+ Codecs: securecookie.CodecsFromPairs(keyPairs...),
+ SessionOpts: &sessions.Options{
+ Path: defaultPath,
+ MaxAge: defaultMaxAge,
+ },
+ }
+ if st.opts.TableName == "" {
+ st.opts.TableName = defaultTableName
+ }
+
+ if !st.opts.SkipCreateTable {
+ if err := st.e.Sync2(&xormSession{tableName: st.opts.TableName}); err != nil {
+ return nil, err
+ }
+ }
+
+ return st, nil
+}
+
+// Get returns a session for the given name after adding it to the registry.
+func (st *Store) Get(r *http.Request, name string) (*sessions.Session, error) {
+ return sessions.GetRegistry(r).Get(st, name)
+}
+
+// New creates a session with name without adding it to the registry.
+func (st *Store) New(r *http.Request, name string) (*sessions.Session, error) {
+ session := sessions.NewSession(st, name)
+ opts := *st.SessionOpts
+ session.Options = &opts
+
+ st.MaxAge(st.SessionOpts.MaxAge)
+
+ // try fetch from db if there is a cookie
+ if cookie, err := r.Cookie(name); err == nil {
+ if err := securecookie.DecodeMulti(name, cookie.Value, &session.ID, st.Codecs...); err != nil {
+ return session, nil
+ }
+ s := &xormSession{tableName: st.opts.TableName}
+ if has, err := st.e.Where("id = ? AND expires_unix >= ?", session.ID, util.TimeStampNow()).Get(s); !has || err != nil {
+ return session, nil
+ }
+ if err := securecookie.DecodeMulti(session.Name(), s.Data, &session.Values, st.Codecs...); err != nil {
+ return session, nil
+ }
+
+ context.Set(r, contextKey(name), s)
+ }
+
+ return session, nil
+}
+
+// Save session and set cookie header
+func (st *Store) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error {
+ s, _ := context.Get(r, contextKey(session.Name())).(*xormSession)
+
+ // delete if max age is < 0
+ if session.Options.MaxAge < 0 {
+ if s != nil {
+ if _, err := st.e.Delete(&xormSession{
+ ID: session.ID,
+ tableName: st.opts.TableName,
+ }); err != nil {
+ return err
+ }
+ }
+ http.SetCookie(w, sessions.NewCookie(session.Name(), "", session.Options))
+ return nil
+ }
+
+ data, err := securecookie.EncodeMulti(session.Name(), session.Values, st.Codecs...)
+ if err != nil {
+ return err
+ }
+ now := util.TimeStampNow()
+ expire := now.AddDuration(time.Second * time.Duration(session.Options.MaxAge))
+
+ if s == nil {
+ // generate random session ID key suitable for storage in the db
+ session.ID = strings.TrimRight(
+ base32.StdEncoding.EncodeToString(
+ securecookie.GenerateRandomKey(sessionIDLen)), "=")
+ s = &xormSession{
+ ID: session.ID,
+ Data: data,
+ CreatedUnix: now,
+ UpdatedUnix: now,
+ ExpiresUnix: expire,
+ tableName: st.opts.TableName,
+ }
+ if _, err := st.e.Insert(s); err != nil {
+ return err
+ }
+ context.Set(r, contextKey(session.Name()), s)
+ } else {
+ s.Data = data
+ s.UpdatedUnix = now
+ s.ExpiresUnix = expire
+ if _, err := st.e.ID(s.ID).Cols("data", "updated_unix", "expires_unix").Update(s); err != nil {
+ return err
+ }
+ }
+
+ // set session id cookie
+ id, err := securecookie.EncodeMulti(session.Name(), session.ID, st.Codecs...)
+ if err != nil {
+ return err
+ }
+ http.SetCookie(w, sessions.NewCookie(session.Name(), id, session.Options))
+
+ return nil
+}
+
+// MaxAge sets the maximum age for the store and the underlying cookie
+// implementation. Individual sessions can be deleted by setting
+// Options.MaxAge = -1 for that session.
+func (st *Store) MaxAge(age int) {
+ st.SessionOpts.MaxAge = age
+ for _, codec := range st.Codecs {
+ if sc, ok := codec.(*securecookie.SecureCookie); ok {
+ sc.MaxAge(age)
+ }
+ }
+}
+
+// MaxLength restricts the maximum length of new sessions to l.
+// If l is 0 there is no limit to the size of a session, use with caution.
+// The default is 4096 (default for securecookie)
+func (st *Store) MaxLength(l int) {
+ for _, c := range st.Codecs {
+ if codec, ok := c.(*securecookie.SecureCookie); ok {
+ codec.MaxLength(l)
+ }
+ }
+}
+
+// Cleanup deletes expired sessions
+func (st *Store) Cleanup() {
+ st.e.Where("expires_unix < ?", util.TimeStampNow()).Delete(&xormSession{tableName: st.opts.TableName})
+}
+
+// PeriodicCleanup runs Cleanup every interval. Close quit channel to stop.
+func (st *Store) PeriodicCleanup(interval time.Duration, quit <-chan struct{}) {
+ t := time.NewTicker(interval)
+ defer t.Stop()
+ for {
+ select {
+ case <-t.C:
+ st.Cleanup()
+ case <-quit:
+ return
+ }
+ }
+}