mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Fix recovery middleware to render gitea style page. (#13857)
* Some changes to fix recovery * Move Recovery to middlewares * Remove trace code * Fix lint * add session middleware and remove dependent on macaron for sso * Fix panic 500 page rendering * Fix bugs * Fix fmt * Fix vendor * recover unnecessary change * Fix lint and addd some comments about the copied codes. * Use util.StatDir instead of com.StatDir Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		
							
								
								
									
										37
									
								
								vendor/gitea.com/go-chi/session/.drone.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/gitea.com/go-chi/session/.drone.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
---
 | 
			
		||||
kind: pipeline
 | 
			
		||||
name: test
 | 
			
		||||
 | 
			
		||||
platform:
 | 
			
		||||
  os: linux
 | 
			
		||||
  arch: amd64
 | 
			
		||||
 | 
			
		||||
clone:
 | 
			
		||||
  disable: true
 | 
			
		||||
 | 
			
		||||
workspace:
 | 
			
		||||
  base: /go
 | 
			
		||||
  path: src/session113
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
- name: git
 | 
			
		||||
  pull: default
 | 
			
		||||
  image: plugins/git:next
 | 
			
		||||
  settings:
 | 
			
		||||
    depth: 50
 | 
			
		||||
    tags: true
 | 
			
		||||
 | 
			
		||||
- name: test
 | 
			
		||||
  pull: default
 | 
			
		||||
  image: golang:1.13
 | 
			
		||||
  environment:
 | 
			
		||||
    GO111MODULE: on
 | 
			
		||||
    GOPROXY: https://goproxy.cn
 | 
			
		||||
  commands:
 | 
			
		||||
    - go build -v
 | 
			
		||||
    - go vet ./...
 | 
			
		||||
    - go test -v -race -coverprofile=coverage.txt -covermode=atomic
 | 
			
		||||
  when:
 | 
			
		||||
    event:
 | 
			
		||||
    - push
 | 
			
		||||
    - pull_request
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/gitea.com/go-chi/session/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/gitea.com/go-chi/session/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
ledis/tmp.db
 | 
			
		||||
nodb/tmp.db
 | 
			
		||||
/vendor
 | 
			
		||||
/.idea
 | 
			
		||||
							
								
								
									
										191
									
								
								vendor/gitea.com/go-chi/session/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/gitea.com/go-chi/session/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
Apache License
 | 
			
		||||
Version 2.0, January 2004
 | 
			
		||||
http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
1. Definitions.
 | 
			
		||||
 | 
			
		||||
"License" shall mean the terms and conditions for use, reproduction, and
 | 
			
		||||
distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
 | 
			
		||||
owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
"Legal Entity" shall mean the union of the acting entity and all other entities
 | 
			
		||||
that control, are controlled by, or are under common control with that entity.
 | 
			
		||||
For the purposes of this definition, "control" means (i) the power, direct or
 | 
			
		||||
indirect, to cause the direction or management of such entity, whether by
 | 
			
		||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
 | 
			
		||||
permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
"Source" form shall mean the preferred form for making modifications, including
 | 
			
		||||
but not limited to software source code, documentation source, and configuration
 | 
			
		||||
files.
 | 
			
		||||
 | 
			
		||||
"Object" form shall mean any form resulting from mechanical transformation or
 | 
			
		||||
translation of a Source form, including but not limited to compiled object code,
 | 
			
		||||
generated documentation, and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
 | 
			
		||||
available under the License, as indicated by a copyright notice that is included
 | 
			
		||||
in or attached to the work (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
 | 
			
		||||
is based on (or derived from) the Work and for which the editorial revisions,
 | 
			
		||||
annotations, elaborations, or other modifications represent, as a whole, an
 | 
			
		||||
original work of authorship. For the purposes of this License, Derivative Works
 | 
			
		||||
shall not include works that remain separable from, or merely link (or bind by
 | 
			
		||||
name) to the interfaces of, the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
"Contribution" shall mean any work of authorship, including the original version
 | 
			
		||||
of the Work and any modifications or additions to that Work or Derivative Works
 | 
			
		||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
 | 
			
		||||
by the copyright owner or by an individual or Legal Entity authorized to submit
 | 
			
		||||
on behalf of the copyright owner. For the purposes of this definition,
 | 
			
		||||
"submitted" means any form of electronic, verbal, or written communication sent
 | 
			
		||||
to the Licensor or its representatives, including but not limited to
 | 
			
		||||
communication on electronic mailing lists, source code control systems, and
 | 
			
		||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
 | 
			
		||||
the purpose of discussing and improving the Work, but excluding communication
 | 
			
		||||
that is conspicuously marked or otherwise designated in writing by the copyright
 | 
			
		||||
owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
 | 
			
		||||
of whom a Contribution has been received by Licensor and subsequently
 | 
			
		||||
incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
2. Grant of Copyright License.
 | 
			
		||||
 | 
			
		||||
Subject to the terms and conditions of this License, each Contributor hereby
 | 
			
		||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
 | 
			
		||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
publicly display, publicly perform, sublicense, and distribute the Work and such
 | 
			
		||||
Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
3. Grant of Patent License.
 | 
			
		||||
 | 
			
		||||
Subject to the terms and conditions of this License, each Contributor hereby
 | 
			
		||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
 | 
			
		||||
irrevocable (except as stated in this section) patent license to make, have
 | 
			
		||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
 | 
			
		||||
such license applies only to those patent claims licensable by such Contributor
 | 
			
		||||
that are necessarily infringed by their Contribution(s) alone or by combination
 | 
			
		||||
of their Contribution(s) with the Work to which such Contribution(s) was
 | 
			
		||||
submitted. If You institute patent litigation against any entity (including a
 | 
			
		||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
 | 
			
		||||
Contribution incorporated within the Work constitutes direct or contributory
 | 
			
		||||
patent infringement, then any patent licenses granted to You under this License
 | 
			
		||||
for that Work shall terminate as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
4. Redistribution.
 | 
			
		||||
 | 
			
		||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
 | 
			
		||||
in any medium, with or without modifications, and in Source or Object form,
 | 
			
		||||
provided that You meet the following conditions:
 | 
			
		||||
 | 
			
		||||
You must give any other recipients of the Work or Derivative Works a copy of
 | 
			
		||||
this License; and
 | 
			
		||||
You must cause any modified files to carry prominent notices stating that You
 | 
			
		||||
changed the files; and
 | 
			
		||||
You must retain, in the Source form of any Derivative Works that You distribute,
 | 
			
		||||
all copyright, patent, trademark, and attribution notices from the Source form
 | 
			
		||||
of the Work, excluding those notices that do not pertain to any part of the
 | 
			
		||||
Derivative Works; and
 | 
			
		||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
 | 
			
		||||
Derivative Works that You distribute must include a readable copy of the
 | 
			
		||||
attribution notices contained within such NOTICE file, excluding those notices
 | 
			
		||||
that do not pertain to any part of the Derivative Works, in at least one of the
 | 
			
		||||
following places: within a NOTICE text file distributed as part of the
 | 
			
		||||
Derivative Works; within the Source form or documentation, if provided along
 | 
			
		||||
with the Derivative Works; or, within a display generated by the Derivative
 | 
			
		||||
Works, if and wherever such third-party notices normally appear. The contents of
 | 
			
		||||
the NOTICE file are for informational purposes only and do not modify the
 | 
			
		||||
License. You may add Your own attribution notices within Derivative Works that
 | 
			
		||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
 | 
			
		||||
provided that such additional attribution notices cannot be construed as
 | 
			
		||||
modifying the License.
 | 
			
		||||
You may add Your own copyright statement to Your modifications and may provide
 | 
			
		||||
additional or different license terms and conditions for use, reproduction, or
 | 
			
		||||
distribution of Your modifications, or for any such Derivative Works as a whole,
 | 
			
		||||
provided Your use, reproduction, and distribution of the Work otherwise complies
 | 
			
		||||
with the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
5. Submission of Contributions.
 | 
			
		||||
 | 
			
		||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
 | 
			
		||||
for inclusion in the Work by You to the Licensor shall be under the terms and
 | 
			
		||||
conditions of this License, without any additional terms or conditions.
 | 
			
		||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
 | 
			
		||||
any separate license agreement you may have executed with Licensor regarding
 | 
			
		||||
such Contributions.
 | 
			
		||||
 | 
			
		||||
6. Trademarks.
 | 
			
		||||
 | 
			
		||||
This License does not grant permission to use the trade names, trademarks,
 | 
			
		||||
service marks, or product names of the Licensor, except as required for
 | 
			
		||||
reasonable and customary use in describing the origin of the Work and
 | 
			
		||||
reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
7. Disclaimer of Warranty.
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, Licensor provides the
 | 
			
		||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
 | 
			
		||||
including, without limitation, any warranties or conditions of TITLE,
 | 
			
		||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
 | 
			
		||||
solely responsible for determining the appropriateness of using or
 | 
			
		||||
redistributing the Work and assume any risks associated with Your exercise of
 | 
			
		||||
permissions under this License.
 | 
			
		||||
 | 
			
		||||
8. Limitation of Liability.
 | 
			
		||||
 | 
			
		||||
In no event and under no legal theory, whether in tort (including negligence),
 | 
			
		||||
contract, or otherwise, unless required by applicable law (such as deliberate
 | 
			
		||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
liable to You for damages, including any direct, indirect, special, incidental,
 | 
			
		||||
or consequential damages of any character arising as a result of this License or
 | 
			
		||||
out of the use or inability to use the Work (including but not limited to
 | 
			
		||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
 | 
			
		||||
any and all other commercial damages or losses), even if such Contributor has
 | 
			
		||||
been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
9. Accepting Warranty or Additional Liability.
 | 
			
		||||
 | 
			
		||||
While redistributing the Work or Derivative Works thereof, You may choose to
 | 
			
		||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
 | 
			
		||||
other liability obligations and/or rights consistent with this License. However,
 | 
			
		||||
in accepting such obligations, You may act only on Your own behalf and on Your
 | 
			
		||||
sole responsibility, not on behalf of any other Contributor, and only if You
 | 
			
		||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
 | 
			
		||||
incurred by, or claims asserted against, such Contributor by reason of your
 | 
			
		||||
accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
APPENDIX: How to apply the Apache License to your work
 | 
			
		||||
 | 
			
		||||
To apply the Apache License to your work, attach the following boilerplate
 | 
			
		||||
notice, with the fields enclosed by brackets "[]" replaced with your own
 | 
			
		||||
identifying information. (Don't include the brackets!) The text should be
 | 
			
		||||
enclosed in the appropriate comment syntax for the file format. We also
 | 
			
		||||
recommend that a file or class name and description of purpose be included on
 | 
			
		||||
the same "printed page" as the copyright notice for easier identification within
 | 
			
		||||
third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   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.
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/gitea.com/go-chi/session/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/gitea.com/go-chi/session/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
# Session
 | 
			
		||||
 | 
			
		||||
Middleware session provides session management which copied from [Macaron Session](https://gitea.com/go-chi/session) for [go-chi](https://github.com/go-chi/chi). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
go get gitea.com/go-chi/session
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Credits
 | 
			
		||||
 | 
			
		||||
This package is a modified version of [go-macaron/session](github.com/go-macaron/session).
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
This project is under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for the full license text.
 | 
			
		||||
							
								
								
									
										227
									
								
								vendor/gitea.com/go-chi/session/couchbase/couchbase.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								vendor/gitea.com/go-chi/session/couchbase/couchbase.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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 (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"gitea.com/go-chi/session"
 | 
			
		||||
	"github.com/couchbase/go-couchbase"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CouchbaseSessionStore represents a couchbase session store implementation.
 | 
			
		||||
type CouchbaseSessionStore struct {
 | 
			
		||||
	b           *couchbase.Bucket
 | 
			
		||||
	sid         string
 | 
			
		||||
	lock        sync.RWMutex
 | 
			
		||||
	data        map[interface{}]interface{}
 | 
			
		||||
	maxlifetime int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *CouchbaseSessionStore) 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 *CouchbaseSessionStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete delete a key from session.
 | 
			
		||||
func (s *CouchbaseSessionStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *CouchbaseSessionStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Release releases resource and save data to provider.
 | 
			
		||||
func (s *CouchbaseSessionStore) Release() error {
 | 
			
		||||
	defer s.b.Close()
 | 
			
		||||
 | 
			
		||||
	// Skip encoding if the data is empty
 | 
			
		||||
	if len(s.data) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := session.EncodeGob(s.data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.b.Set(s.sid, int(s.maxlifetime), data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *CouchbaseSessionStore) Flush() error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	s.data = make(map[interface{}]interface{})
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CouchbaseProvider represents a couchbase session provider implementation.
 | 
			
		||||
type CouchbaseProvider struct {
 | 
			
		||||
	maxlifetime int64
 | 
			
		||||
	connStr     string
 | 
			
		||||
	pool        string
 | 
			
		||||
	bucket      string
 | 
			
		||||
	b           *couchbase.Bucket
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
 | 
			
		||||
	c, err := couchbase.Connect(cp.connStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pool, err := c.GetPool(cp.pool)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bucket, err := pool.GetBucket(cp.bucket)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bucket
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initializes memory session provider.
 | 
			
		||||
// connStr is couchbase server REST/JSON URL
 | 
			
		||||
// e.g. http://host:port/, Pool, Bucket
 | 
			
		||||
func (p *CouchbaseProvider) Init(maxlifetime int64, connStr string) error {
 | 
			
		||||
	p.maxlifetime = maxlifetime
 | 
			
		||||
	configs := strings.Split(connStr, ",")
 | 
			
		||||
	if len(configs) > 0 {
 | 
			
		||||
		p.connStr = configs[0]
 | 
			
		||||
	}
 | 
			
		||||
	if len(configs) > 1 {
 | 
			
		||||
		p.pool = configs[1]
 | 
			
		||||
	}
 | 
			
		||||
	if len(configs) > 2 {
 | 
			
		||||
		p.bucket = configs[2]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read returns raw session store by session ID.
 | 
			
		||||
func (p *CouchbaseProvider) Read(sid string) (session.RawStore, error) {
 | 
			
		||||
	p.b = p.getBucket()
 | 
			
		||||
 | 
			
		||||
	var doc []byte
 | 
			
		||||
 | 
			
		||||
	err := p.b.Get(sid, &doc)
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	if doc == nil {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(doc)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
 | 
			
		||||
	return cs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exist returns true if session with given ID exists.
 | 
			
		||||
func (p *CouchbaseProvider) Exist(sid string) bool {
 | 
			
		||||
	p.b = p.getBucket()
 | 
			
		||||
	defer p.b.Close()
 | 
			
		||||
 | 
			
		||||
	var doc []byte
 | 
			
		||||
 | 
			
		||||
	if err := p.b.Get(sid, &doc); err != nil || doc == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	} else {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *CouchbaseProvider) Destroy(sid string) error {
 | 
			
		||||
	p.b = p.getBucket()
 | 
			
		||||
	defer p.b.Close()
 | 
			
		||||
 | 
			
		||||
	p.b.Delete(sid)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Regenerate regenerates a session store from old session ID to new one.
 | 
			
		||||
func (p *CouchbaseProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
 | 
			
		||||
	p.b = p.getBucket()
 | 
			
		||||
 | 
			
		||||
	var doc []byte
 | 
			
		||||
	if err := p.b.Get(oldsid, &doc); err != nil || doc == nil {
 | 
			
		||||
		p.b.Set(sid, int(p.maxlifetime), "")
 | 
			
		||||
	} else {
 | 
			
		||||
		err := p.b.Delete(oldsid)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		_, _ = p.b.Add(sid, int(p.maxlifetime), doc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := p.b.Get(sid, &doc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	if doc == nil {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(doc)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cs := &CouchbaseSessionStore{b: p.b, sid: sid, data: kv, maxlifetime: p.maxlifetime}
 | 
			
		||||
	return cs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count counts and returns number of sessions.
 | 
			
		||||
func (p *CouchbaseProvider) Count() int {
 | 
			
		||||
	// FIXME
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GC calls GC to clean expired sessions.
 | 
			
		||||
func (p *CouchbaseProvider) GC() {}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	session.Register("couchbase", &CouchbaseProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										274
									
								
								vendor/gitea.com/go-chi/session/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								vendor/gitea.com/go-chi/session/file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,274 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FileStore represents a file session store implementation.
 | 
			
		||||
type FileStore struct {
 | 
			
		||||
	p    *FileProvider
 | 
			
		||||
	sid  string
 | 
			
		||||
	lock sync.RWMutex
 | 
			
		||||
	data map[interface{}]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewFileStore creates and returns a file session store.
 | 
			
		||||
func NewFileStore(p *FileProvider, sid string, kv map[interface{}]interface{}) *FileStore {
 | 
			
		||||
	return &FileStore{
 | 
			
		||||
		p:    p,
 | 
			
		||||
		sid:  sid,
 | 
			
		||||
		data: kv,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *FileStore) 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 *FileStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete delete a key from session.
 | 
			
		||||
func (s *FileStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *FileStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Release releases resource and save data to provider.
 | 
			
		||||
func (s *FileStore) Release() error {
 | 
			
		||||
	s.p.lock.Lock()
 | 
			
		||||
	defer s.p.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	// Skip encoding if the data is empty
 | 
			
		||||
	if len(s.data) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := EncodeGob(s.data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ioutil.WriteFile(s.p.filepath(s.sid), data, 0600)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *FileStore) 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.lock.Lock()
 | 
			
		||||
	p.maxlifetime = maxlifetime
 | 
			
		||||
	p.rootPath = rootPath
 | 
			
		||||
	p.lock.Unlock()
 | 
			
		||||
	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) {
 | 
			
		||||
	filename := p.filepath(sid)
 | 
			
		||||
	if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	p.lock.RLock()
 | 
			
		||||
	defer p.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	var f *os.File
 | 
			
		||||
	ok := false
 | 
			
		||||
	if com.IsFile(filename) {
 | 
			
		||||
		modTime, err := com.FileMTime(filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		ok = (modTime + p.maxlifetime) >= time.Now().Unix()
 | 
			
		||||
	}
 | 
			
		||||
	if ok {
 | 
			
		||||
		f, err = os.OpenFile(filename, os.O_RDONLY, 0600)
 | 
			
		||||
	} 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 NewFileStore(p, sid, kv), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exist returns true if session with given ID exists.
 | 
			
		||||
func (p *FileProvider) Exist(sid string) bool {
 | 
			
		||||
	p.lock.RLock()
 | 
			
		||||
	defer p.lock.RUnlock()
 | 
			
		||||
	return com.IsFile(p.filepath(sid))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *FileProvider) Destroy(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) {
 | 
			
		||||
	p.lock.Lock()
 | 
			
		||||
	defer p.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	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), 0700); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err = ioutil.WriteFile(oldname, data, 0600); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = os.MkdirAll(path.Dir(filename), 0700); 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) {
 | 
			
		||||
	if err := p.regenerate(oldsid, sid); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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() {
 | 
			
		||||
	p.lock.RLock()
 | 
			
		||||
	defer p.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if !com.IsExist(p.rootPath) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/gitea.com/go-chi/session/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/gitea.com/go-chi/session/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
module gitea.com/go-chi/session
 | 
			
		||||
 | 
			
		||||
go 1.11
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668
 | 
			
		||||
	github.com/couchbase/go-couchbase v0.0.0-20201026062457-7b3be89bbd89
 | 
			
		||||
	github.com/couchbase/gomemcached v0.1.1 // indirect
 | 
			
		||||
	github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67 // indirect
 | 
			
		||||
	github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
 | 
			
		||||
	github.com/edsrzf/mmap-go v1.0.0 // indirect
 | 
			
		||||
	github.com/go-chi/chi v1.5.1
 | 
			
		||||
	github.com/go-redis/redis/v8 v8.4.0
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.4.1
 | 
			
		||||
	github.com/lib/pq v1.2.0
 | 
			
		||||
	github.com/pelletier/go-toml v1.8.1 // indirect
 | 
			
		||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
			
		||||
	github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect
 | 
			
		||||
	github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92
 | 
			
		||||
	github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect
 | 
			
		||||
	github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
 | 
			
		||||
	github.com/syndtr/goleveldb v1.0.0 // indirect
 | 
			
		||||
	github.com/unknwon/com v1.0.1
 | 
			
		||||
	google.golang.org/appengine v1.6.7 // indirect
 | 
			
		||||
	gopkg.in/ini.v1 v1.62.0
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										151
									
								
								vendor/gitea.com/go-chi/session/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								vendor/gitea.com/go-chi/session/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/couchbase/go-couchbase v0.0.0-20201026062457-7b3be89bbd89 h1:uNLXQ6QO1TocD8BaN/KkRki0Xw0brCM1PKl/ZA5pgfs=
 | 
			
		||||
github.com/couchbase/go-couchbase v0.0.0-20201026062457-7b3be89bbd89/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
 | 
			
		||||
github.com/couchbase/gomemcached v0.1.1 h1:xCS8ZglJDhrlQg3jmK7Rn1V8f7bPjXABLC05CgLQauc=
 | 
			
		||||
github.com/couchbase/gomemcached v0.1.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67 h1:NCqJ6fwen6YP0WlV/IyibaT0kPt3JEI1rA62V/UPKT4=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
 | 
			
		||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 h1:Lgdd/Qp96Qj8jqLpq2cI1I1X7BJnu06efS+XkhRoLUQ=
 | 
			
		||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 | 
			
		||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 | 
			
		||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
 | 
			
		||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 | 
			
		||||
github.com/go-chi/chi v1.5.1 h1:kfTK3Cxd/dkMu/rKs5ZceWYp+t5CtiE7vmaTv3LjC6w=
 | 
			
		||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
 | 
			
		||||
github.com/go-redis/redis/v8 v8.4.0 h1:J5NCReIgh3QgUJu398hUncxDExN4gMOHI11NVbVicGQ=
 | 
			
		||||
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 | 
			
		||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 | 
			
		||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 | 
			
		||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 | 
			
		||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
 | 
			
		||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 | 
			
		||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 | 
			
		||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
 | 
			
		||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
 | 
			
		||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 | 
			
		||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
			
		||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 | 
			
		||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 | 
			
		||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 | 
			
		||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
 | 
			
		||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 | 
			
		||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 | 
			
		||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
 | 
			
		||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 | 
			
		||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
 | 
			
		||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 | 
			
		||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
 | 
			
		||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 | 
			
		||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 | 
			
		||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
 | 
			
		||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
 | 
			
		||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
 | 
			
		||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
 | 
			
		||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 | 
			
		||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
 | 
			
		||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 | 
			
		||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92 h1:qvsJwGToa8rxb42cDRhkbKeX2H5N8BH+s2aUikGt8mI=
 | 
			
		||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
 | 
			
		||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d h1:NVwnfyR3rENtlz62bcrkXME3INVUa4lcdGt+opvxExs=
 | 
			
		||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 | 
			
		||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 | 
			
		||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
 | 
			
		||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
 | 
			
		||||
go.opentelemetry.io/otel v0.14.0 h1:YFBEfjCk9MTjaytCNSUkp9Q8lF7QJezA06T71FbQxLQ=
 | 
			
		||||
go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 | 
			
		||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 | 
			
		||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
 | 
			
		||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
			
		||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
 | 
			
		||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
			
		||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
			
		||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 | 
			
		||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 | 
			
		||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
			
		||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 | 
			
		||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 | 
			
		||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 | 
			
		||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 | 
			
		||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
 | 
			
		||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
 | 
			
		||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 | 
			
		||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 | 
			
		||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
 | 
			
		||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 | 
			
		||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
							
								
								
									
										203
									
								
								vendor/gitea.com/go-chi/session/memcache/memcache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								vendor/gitea.com/go-chi/session/memcache/memcache.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,203 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"gitea.com/go-chi/session"
 | 
			
		||||
	"github.com/bradfitz/gomemcache/memcache"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MemcacheStore represents a memcache session store implementation.
 | 
			
		||||
type MemcacheStore struct {
 | 
			
		||||
	c      *memcache.Client
 | 
			
		||||
	sid    string
 | 
			
		||||
	expire int32
 | 
			
		||||
	lock   sync.RWMutex
 | 
			
		||||
	data   map[interface{}]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMemcacheStore creates and returns a memcache session store.
 | 
			
		||||
func NewMemcacheStore(c *memcache.Client, sid string, expire int32, kv map[interface{}]interface{}) *MemcacheStore {
 | 
			
		||||
	return &MemcacheStore{
 | 
			
		||||
		c:      c,
 | 
			
		||||
		sid:    sid,
 | 
			
		||||
		expire: expire,
 | 
			
		||||
		data:   kv,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewItem(sid string, data []byte, expire int32) *memcache.Item {
 | 
			
		||||
	return &memcache.Item{
 | 
			
		||||
		Key:        sid,
 | 
			
		||||
		Value:      data,
 | 
			
		||||
		Expiration: expire,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *MemcacheStore) 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 *MemcacheStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete delete a key from session.
 | 
			
		||||
func (s *MemcacheStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *MemcacheStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Release releases resource and save data to provider.
 | 
			
		||||
func (s *MemcacheStore) Release() error {
 | 
			
		||||
	// Skip encoding if the data is empty
 | 
			
		||||
	if len(s.data) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := session.EncodeGob(s.data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return s.c.Set(NewItem(s.sid, data, s.expire))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *MemcacheStore) Flush() error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	s.data = make(map[interface{}]interface{})
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MemcacheProvider represents a memcache session provider implementation.
 | 
			
		||||
type MemcacheProvider struct {
 | 
			
		||||
	c      *memcache.Client
 | 
			
		||||
	expire int32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initializes memcache session provider.
 | 
			
		||||
// connStrs: 127.0.0.1:9090;127.0.0.1:9091
 | 
			
		||||
func (p *MemcacheProvider) Init(expire int64, connStrs string) error {
 | 
			
		||||
	p.expire = int32(expire)
 | 
			
		||||
	p.c = memcache.New(strings.Split(connStrs, ";")...)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read returns raw session store by session ID.
 | 
			
		||||
func (p *MemcacheProvider) Read(sid string) (session.RawStore, error) {
 | 
			
		||||
	if !p.Exist(sid) {
 | 
			
		||||
		if err := p.c.Set(NewItem(sid, []byte(""), p.expire)); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	item, err := p.c.Get(sid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(item.Value) == 0 {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(item.Value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewMemcacheStore(p.c, sid, p.expire, kv), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exist returns true if session with given ID exists.
 | 
			
		||||
func (p *MemcacheProvider) Exist(sid string) bool {
 | 
			
		||||
	_, err := p.c.Get(sid)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *MemcacheProvider) Destroy(sid string) error {
 | 
			
		||||
	return p.c.Delete(sid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Regenerate regenerates a session store from old session ID to new one.
 | 
			
		||||
func (p *MemcacheProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
 | 
			
		||||
	if p.Exist(sid) {
 | 
			
		||||
		return nil, fmt.Errorf("new sid '%s' already exists", sid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	item := NewItem(sid, []byte(""), p.expire)
 | 
			
		||||
	if p.Exist(oldsid) {
 | 
			
		||||
		item, err = p.c.Get(oldsid)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		} else if err = p.c.Delete(oldsid); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		item.Key = sid
 | 
			
		||||
	}
 | 
			
		||||
	if err = p.c.Set(item); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	if len(item.Value) == 0 {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(item.Value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewMemcacheStore(p.c, sid, p.expire, kv), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count counts and returns number of sessions.
 | 
			
		||||
func (p *MemcacheProvider) Count() int {
 | 
			
		||||
	// FIXME: how come this library does not have Stats method?
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GC calls GC to clean expired sessions.
 | 
			
		||||
func (p *MemcacheProvider) GC() {}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	session.Register("memcache", &MemcacheProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/gitea.com/go-chi/session/memcache/memcache.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/gitea.com/go-chi/session/memcache/memcache.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ignore
 | 
			
		||||
							
								
								
									
										223
									
								
								vendor/gitea.com/go-chi/session/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								vendor/gitea.com/go-chi/session/memory.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MemStore represents a in-memory session store implementation.
 | 
			
		||||
type MemStore struct {
 | 
			
		||||
	sid        string
 | 
			
		||||
	lock       sync.RWMutex
 | 
			
		||||
	data       map[interface{}]interface{}
 | 
			
		||||
	lastAccess time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMemStore creates and returns a memory session store.
 | 
			
		||||
func NewMemStore(sid string) *MemStore {
 | 
			
		||||
	return &MemStore{
 | 
			
		||||
		sid:        sid,
 | 
			
		||||
		data:       make(map[interface{}]interface{}),
 | 
			
		||||
		lastAccess: time.Now(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *MemStore) 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 *MemStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete deletes a key from session.
 | 
			
		||||
func (s *MemStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *MemStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Release releases resource and save data to provider.
 | 
			
		||||
func (*MemStore) Release() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *MemStore) 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.lock.Lock()
 | 
			
		||||
	p.list = list.New()
 | 
			
		||||
	p.data = make(map[string]*list.Element)
 | 
			
		||||
	p.maxLifetime = maxLifetime
 | 
			
		||||
	p.lock.Unlock()
 | 
			
		||||
	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.(*MemStore).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()
 | 
			
		||||
 | 
			
		||||
	// Only restore if the session is still alive.
 | 
			
		||||
	if ok && (e.Value.(*MemStore).lastAccess.Unix()+p.maxLifetime) >= time.Now().Unix() {
 | 
			
		||||
		if err = p.update(sid); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return e.Value.(*MemStore), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create a new session.
 | 
			
		||||
	p.lock.Lock()
 | 
			
		||||
	defer p.lock.Unlock()
 | 
			
		||||
	if ok {
 | 
			
		||||
		p.list.Remove(e)
 | 
			
		||||
		delete(p.data, sid)
 | 
			
		||||
	}
 | 
			
		||||
	s := NewMemStore(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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *MemProvider) Destroy(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.Destroy(oldsid); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.(*MemStore).sid = sid
 | 
			
		||||
 | 
			
		||||
	p.lock.Lock()
 | 
			
		||||
	defer p.lock.Unlock()
 | 
			
		||||
	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.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
 | 
			
		||||
			p.lock.RUnlock()
 | 
			
		||||
			p.lock.Lock()
 | 
			
		||||
			p.list.Remove(e)
 | 
			
		||||
			delete(p.data, e.Value.(*MemStore).sid)
 | 
			
		||||
			p.lock.Unlock()
 | 
			
		||||
			p.lock.RLock()
 | 
			
		||||
		} else {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	p.lock.RUnlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Register("memory", &MemProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										201
									
								
								vendor/gitea.com/go-chi/session/mysql/mysql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								vendor/gitea.com/go-chi/session/mysql/mysql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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 (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gitea.com/go-chi/session"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MysqlStore represents a mysql session store implementation.
 | 
			
		||||
type MysqlStore struct {
 | 
			
		||||
	c    *sql.DB
 | 
			
		||||
	sid  string
 | 
			
		||||
	lock sync.RWMutex
 | 
			
		||||
	data map[interface{}]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMysqlStore creates and returns a mysql session store.
 | 
			
		||||
func NewMysqlStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *MysqlStore {
 | 
			
		||||
	return &MysqlStore{
 | 
			
		||||
		c:    c,
 | 
			
		||||
		sid:  sid,
 | 
			
		||||
		data: kv,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *MysqlStore) 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 *MysqlStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete delete a key from session.
 | 
			
		||||
func (s *MysqlStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *MysqlStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Release releases resource and save data to provider.
 | 
			
		||||
func (s *MysqlStore) Release() error {
 | 
			
		||||
	// Skip encoding if the data is empty
 | 
			
		||||
	if len(s.data) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := session.EncodeGob(s.data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = s.c.Exec("UPDATE session SET data=?, expiry=? WHERE `key`=?",
 | 
			
		||||
		data, time.Now().Unix(), s.sid)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *MysqlStore) Flush() error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	s.data = make(map[interface{}]interface{})
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MysqlProvider represents a mysql session provider implementation.
 | 
			
		||||
type MysqlProvider struct {
 | 
			
		||||
	c      *sql.DB
 | 
			
		||||
	expire int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initializes mysql session provider.
 | 
			
		||||
// connStr: username:password@protocol(address)/dbname?param=value
 | 
			
		||||
func (p *MysqlProvider) Init(expire int64, connStr string) (err error) {
 | 
			
		||||
	p.expire = expire
 | 
			
		||||
 | 
			
		||||
	p.c, err = sql.Open("mysql", connStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return p.c.Ping()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read returns raw session store by session ID.
 | 
			
		||||
func (p *MysqlProvider) Read(sid string) (session.RawStore, error) {
 | 
			
		||||
	now := time.Now().Unix()
 | 
			
		||||
	var data []byte
 | 
			
		||||
	expiry := now
 | 
			
		||||
	err := p.c.QueryRow("SELECT data, expiry FROM session WHERE `key`=?", sid).Scan(&data, &expiry)
 | 
			
		||||
	if err == sql.ErrNoRows {
 | 
			
		||||
		_, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
 | 
			
		||||
			sid, "", now)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	if len(data) == 0 || expiry+p.expire <= now {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewMysqlStore(p.c, sid, kv), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exist returns true if session with given ID exists.
 | 
			
		||||
func (p *MysqlProvider) Exist(sid string) bool {
 | 
			
		||||
	var data []byte
 | 
			
		||||
	err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data)
 | 
			
		||||
	if err != nil && err != sql.ErrNoRows {
 | 
			
		||||
		panic("session/mysql: error checking existence: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return err != sql.ErrNoRows
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *MysqlProvider) Destroy(sid string) error {
 | 
			
		||||
	_, err := p.c.Exec("DELETE FROM session WHERE `key`=?", sid)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Regenerate regenerates a session store from old session ID to new one.
 | 
			
		||||
func (p *MysqlProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
 | 
			
		||||
	if p.Exist(sid) {
 | 
			
		||||
		return nil, fmt.Errorf("new sid '%s' already exists", sid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !p.Exist(oldsid) {
 | 
			
		||||
		if _, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)",
 | 
			
		||||
			oldsid, "", time.Now().Unix()); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err = p.c.Exec("UPDATE session SET `key`=? WHERE `key`=?", sid, oldsid); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p.Read(sid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count counts and returns number of sessions.
 | 
			
		||||
func (p *MysqlProvider) Count() (total int) {
 | 
			
		||||
	if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
 | 
			
		||||
		panic("session/mysql: error counting records: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return total
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GC calls GC to clean expired sessions.
 | 
			
		||||
func (p *MysqlProvider) GC() {
 | 
			
		||||
	if _, err := p.c.Exec("DELETE FROM session WHERE  expiry + ? <= UNIX_TIMESTAMP(NOW())", p.expire); err != nil {
 | 
			
		||||
		log.Printf("session/mysql: error garbage collecting: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	session.Register("mysql", &MysqlProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/gitea.com/go-chi/session/mysql/mysql.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/gitea.com/go-chi/session/mysql/mysql.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ignore
 | 
			
		||||
							
								
								
									
										202
									
								
								vendor/gitea.com/go-chi/session/postgres/postgres.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								vendor/gitea.com/go-chi/session/postgres/postgres.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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 (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gitea.com/go-chi/session"
 | 
			
		||||
	_ "github.com/lib/pq"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PostgresStore represents a postgres session store implementation.
 | 
			
		||||
type PostgresStore struct {
 | 
			
		||||
	c    *sql.DB
 | 
			
		||||
	sid  string
 | 
			
		||||
	lock sync.RWMutex
 | 
			
		||||
	data map[interface{}]interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewPostgresStore creates and returns a postgres session store.
 | 
			
		||||
func NewPostgresStore(c *sql.DB, sid string, kv map[interface{}]interface{}) *PostgresStore {
 | 
			
		||||
	return &PostgresStore{
 | 
			
		||||
		c:    c,
 | 
			
		||||
		sid:  sid,
 | 
			
		||||
		data: kv,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets value to given key in session.
 | 
			
		||||
func (s *PostgresStore) Set(key, value interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	s.data[key] = value
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get gets value by given key in session.
 | 
			
		||||
func (s *PostgresStore) Get(key interface{}) interface{} {
 | 
			
		||||
	s.lock.RLock()
 | 
			
		||||
	defer s.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return s.data[key]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete delete a key from session.
 | 
			
		||||
func (s *PostgresStore) Delete(key interface{}) error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	delete(s.data, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ID returns current session ID.
 | 
			
		||||
func (s *PostgresStore) ID() string {
 | 
			
		||||
	return s.sid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// save postgres session values to database.
 | 
			
		||||
// must call this method to save values to database.
 | 
			
		||||
func (s *PostgresStore) Release() error {
 | 
			
		||||
	// Skip encoding if the data is empty
 | 
			
		||||
	if len(s.data) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := session.EncodeGob(s.data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = s.c.Exec("UPDATE session SET data=$1, expiry=$2 WHERE key=$3",
 | 
			
		||||
		data, time.Now().Unix(), s.sid)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Flush deletes all session data.
 | 
			
		||||
func (s *PostgresStore) Flush() error {
 | 
			
		||||
	s.lock.Lock()
 | 
			
		||||
	defer s.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	s.data = make(map[interface{}]interface{})
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PostgresProvider represents a postgres session provider implementation.
 | 
			
		||||
type PostgresProvider struct {
 | 
			
		||||
	c           *sql.DB
 | 
			
		||||
	maxlifetime int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initializes postgres session provider.
 | 
			
		||||
// connStr: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
 | 
			
		||||
func (p *PostgresProvider) Init(maxlifetime int64, connStr string) (err error) {
 | 
			
		||||
	p.maxlifetime = maxlifetime
 | 
			
		||||
 | 
			
		||||
	p.c, err = sql.Open("postgres", connStr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return p.c.Ping()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read returns raw session store by session ID.
 | 
			
		||||
func (p *PostgresProvider) Read(sid string) (session.RawStore, error) {
 | 
			
		||||
	now := time.Now().Unix()
 | 
			
		||||
	var data []byte
 | 
			
		||||
	expiry := now
 | 
			
		||||
	err := p.c.QueryRow("SELECT data, expiry FROM session WHERE key=$1", sid).Scan(&data, &expiry)
 | 
			
		||||
	if err == sql.ErrNoRows {
 | 
			
		||||
		_, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
 | 
			
		||||
			sid, "", now)
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var kv map[interface{}]interface{}
 | 
			
		||||
	if len(data) == 0 || expiry+p.maxlifetime <= now {
 | 
			
		||||
		kv = make(map[interface{}]interface{})
 | 
			
		||||
	} else {
 | 
			
		||||
		kv, err = session.DecodeGob(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NewPostgresStore(p.c, sid, kv), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exist returns true if session with given ID exists.
 | 
			
		||||
func (p *PostgresProvider) Exist(sid string) bool {
 | 
			
		||||
	var data []byte
 | 
			
		||||
	err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data)
 | 
			
		||||
	if err != nil && err != sql.ErrNoRows {
 | 
			
		||||
		panic("session/postgres: error checking existence: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return err != sql.ErrNoRows
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by session ID.
 | 
			
		||||
func (p *PostgresProvider) Destroy(sid string) error {
 | 
			
		||||
	_, err := p.c.Exec("DELETE FROM session WHERE key=$1", sid)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Regenerate regenerates a session store from old session ID to new one.
 | 
			
		||||
func (p *PostgresProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
 | 
			
		||||
	if p.Exist(sid) {
 | 
			
		||||
		return nil, fmt.Errorf("new sid '%s' already exists", sid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !p.Exist(oldsid) {
 | 
			
		||||
		if _, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)",
 | 
			
		||||
			oldsid, "", time.Now().Unix()); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err = p.c.Exec("UPDATE session SET key=$1 WHERE key=$2", sid, oldsid); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p.Read(sid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count counts and returns number of sessions.
 | 
			
		||||
func (p *PostgresProvider) Count() (total int) {
 | 
			
		||||
	if err := p.c.QueryRow("SELECT COUNT(*) AS NUM FROM session").Scan(&total); err != nil {
 | 
			
		||||
		panic("session/postgres: error counting records: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return total
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GC calls GC to clean expired sessions.
 | 
			
		||||
func (p *PostgresProvider) GC() {
 | 
			
		||||
	if _, err := p.c.Exec("DELETE FROM session WHERE EXTRACT(EPOCH FROM NOW()) - expiry > $1", p.maxlifetime); err != nil {
 | 
			
		||||
		log.Printf("session/postgres: error garbage collecting: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	session.Register("postgres", &PostgresProvider{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/gitea.com/go-chi/session/postgres/postgres.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/gitea.com/go-chi/session/postgres/postgres.goconvey
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ignore
 | 
			
		||||
							
								
								
									
										100
									
								
								vendor/gitea.com/go-chi/session/secret.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/gitea.com/go-chi/session/secret.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package session
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/aes"
 | 
			
		||||
	"crypto/cipher"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewSecret creates a new secret
 | 
			
		||||
func NewSecret() (string, error) {
 | 
			
		||||
	return NewSecretWithLength(32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSecretWithLength creates a new secret for a given length
 | 
			
		||||
func NewSecretWithLength(length int64) (string, error) {
 | 
			
		||||
	return randomString(length)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func randomBytes(len int64) ([]byte, error) {
 | 
			
		||||
	b := make([]byte, len)
 | 
			
		||||
	if _, err := rand.Read(b); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func randomString(len int64) (string, error) {
 | 
			
		||||
	b, err := randomBytes(len)
 | 
			
		||||
	return base64.URLEncoding.EncodeToString(b), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AesEncrypt encrypts text and given key with AES.
 | 
			
		||||
func AesEncrypt(key, text []byte) ([]byte, error) {
 | 
			
		||||
	block, err := aes.NewCipher(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	b := base64.StdEncoding.EncodeToString(text)
 | 
			
		||||
	ciphertext := make([]byte, aes.BlockSize+len(b))
 | 
			
		||||
	iv := ciphertext[:aes.BlockSize]
 | 
			
		||||
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	cfb := cipher.NewCFBEncrypter(block, iv)
 | 
			
		||||
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
 | 
			
		||||
	return ciphertext, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AesDecrypt decrypts text and given key with AES.
 | 
			
		||||
func AesDecrypt(key, text []byte) ([]byte, error) {
 | 
			
		||||
	block, err := aes.NewCipher(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(text) < aes.BlockSize {
 | 
			
		||||
		return nil, errors.New("ciphertext too short")
 | 
			
		||||
	}
 | 
			
		||||
	iv := text[:aes.BlockSize]
 | 
			
		||||
	text = text[aes.BlockSize:]
 | 
			
		||||
	cfb := cipher.NewCFBDecrypter(block, iv)
 | 
			
		||||
	cfb.XORKeyStream(text, text)
 | 
			
		||||
	data, err := base64.StdEncoding.DecodeString(string(text))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncryptSecret encrypts a string with given key into a hex string
 | 
			
		||||
func EncryptSecret(key string, str string) (string, error) {
 | 
			
		||||
	keyHash := sha256.Sum256([]byte(key))
 | 
			
		||||
	plaintext := []byte(str)
 | 
			
		||||
	ciphertext, err := AesEncrypt(keyHash[:], plaintext)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return base64.StdEncoding.EncodeToString(ciphertext), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecryptSecret decrypts a previously encrypted hex string
 | 
			
		||||
func DecryptSecret(key string, cipherhex string) (string, error) {
 | 
			
		||||
	keyHash := sha256.Sum256([]byte(key))
 | 
			
		||||
	ciphertext, err := base64.StdEncoding.DecodeString(cipherhex)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	plaintext, err := AesDecrypt(keyHash[:], ciphertext)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return string(plaintext), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										466
									
								
								vendor/gitea.com/go-chi/session/session.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								vendor/gitea.com/go-chi/session/session.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,466 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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 a middleware that provides the session management of Macaron.
 | 
			
		||||
package session
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const version = "0.7.0"
 | 
			
		||||
 | 
			
		||||
// Version returns the version
 | 
			
		||||
func Version() string {
 | 
			
		||||
	return version
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RawStore is the interface that operates the session data.
 | 
			
		||||
type RawStore interface {
 | 
			
		||||
	// Set sets value to given key in session.
 | 
			
		||||
	Set(interface{}, interface{}) error
 | 
			
		||||
	// Get gets value by given key in session.
 | 
			
		||||
	Get(interface{}) interface{}
 | 
			
		||||
	// Delete deletes a key from session.
 | 
			
		||||
	Delete(interface{}) error
 | 
			
		||||
	// ID returns current session ID.
 | 
			
		||||
	ID() string
 | 
			
		||||
	// Release releases session resource and save data to provider.
 | 
			
		||||
	Release() error
 | 
			
		||||
	// Flush deletes all session data.
 | 
			
		||||
	Flush() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Store is the interface that contains all data for one session process with specific ID.
 | 
			
		||||
type Store interface {
 | 
			
		||||
	RawStore
 | 
			
		||||
	// Read returns raw session store by session ID.
 | 
			
		||||
	Read(string) (RawStore, error)
 | 
			
		||||
	// Destroy deletes a session.
 | 
			
		||||
	Destroy(http.ResponseWriter, *http.Request) error
 | 
			
		||||
	// RegenerateID regenerates a session store from old session ID to new one.
 | 
			
		||||
	RegenerateID(http.ResponseWriter, *http.Request) (RawStore, error)
 | 
			
		||||
	// Count counts and returns number of sessions.
 | 
			
		||||
	Count() int
 | 
			
		||||
	// GC calls GC to clean expired sessions.
 | 
			
		||||
	GC()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type store struct {
 | 
			
		||||
	RawStore
 | 
			
		||||
	*Manager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Store = &store{}
 | 
			
		||||
 | 
			
		||||
// Options represents a struct for specifying configuration options for the session middleware.
 | 
			
		||||
type Options struct {
 | 
			
		||||
	// Name of provider. Default is "memory".
 | 
			
		||||
	Provider string
 | 
			
		||||
	// Provider configuration, it's corresponding to provider.
 | 
			
		||||
	ProviderConfig string
 | 
			
		||||
	// Cookie name to save session ID. Default is "MacaronSession".
 | 
			
		||||
	CookieName string
 | 
			
		||||
	// Cookie path to store. Default is "/".
 | 
			
		||||
	CookiePath string
 | 
			
		||||
	// GC interval time in seconds. Default is 3600.
 | 
			
		||||
	Gclifetime int64
 | 
			
		||||
	// Max life time in seconds. Default is whatever GC interval time is.
 | 
			
		||||
	Maxlifetime int64
 | 
			
		||||
	// Use HTTPS only. Default is false.
 | 
			
		||||
	Secure bool
 | 
			
		||||
	// Cookie life time. Default is 0.
 | 
			
		||||
	CookieLifeTime int
 | 
			
		||||
	// SameSite set the cookie SameSite
 | 
			
		||||
	SameSite http.SameSite
 | 
			
		||||
	// Cookie domain name. Default is empty.
 | 
			
		||||
	Domain string
 | 
			
		||||
	// Session ID length. Default is 16.
 | 
			
		||||
	IDLength int
 | 
			
		||||
	// Ignore release for websocket. Default is false.
 | 
			
		||||
	IgnoreReleaseForWebSocket bool
 | 
			
		||||
	// FlashEncryptionKey sets the encryption key for flash messages
 | 
			
		||||
	FlashEncryptionKey string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func prepareOptions(options []Options) Options {
 | 
			
		||||
	var opt Options
 | 
			
		||||
	if len(options) > 0 {
 | 
			
		||||
		opt = options[0]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opt.Provider) == 0 {
 | 
			
		||||
		opt.Provider = "memory"
 | 
			
		||||
	}
 | 
			
		||||
	if len(opt.ProviderConfig) == 0 {
 | 
			
		||||
		opt.ProviderConfig = "data/sessions"
 | 
			
		||||
	}
 | 
			
		||||
	if len(opt.CookieName) == 0 {
 | 
			
		||||
		opt.CookieName = "MacaronSession"
 | 
			
		||||
	}
 | 
			
		||||
	if len(opt.CookiePath) == 0 {
 | 
			
		||||
		opt.CookiePath = "/"
 | 
			
		||||
	}
 | 
			
		||||
	if opt.Gclifetime == 0 {
 | 
			
		||||
		opt.Gclifetime = 3600
 | 
			
		||||
	}
 | 
			
		||||
	if opt.Maxlifetime == 0 {
 | 
			
		||||
		opt.Maxlifetime = opt.Gclifetime
 | 
			
		||||
	}
 | 
			
		||||
	if !opt.Secure {
 | 
			
		||||
		opt.Secure = false
 | 
			
		||||
	}
 | 
			
		||||
	if opt.IDLength == 0 {
 | 
			
		||||
		opt.IDLength = 16
 | 
			
		||||
	}
 | 
			
		||||
	if len(opt.FlashEncryptionKey) == 0 {
 | 
			
		||||
		opt.FlashEncryptionKey = ""
 | 
			
		||||
	}
 | 
			
		||||
	if len(opt.FlashEncryptionKey) == 0 {
 | 
			
		||||
		opt.FlashEncryptionKey, _ = NewSecret()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return opt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetCookie returns given cookie value from request header.
 | 
			
		||||
func GetCookie(req *http.Request, name string) string {
 | 
			
		||||
	cookie, err := req.Cookie(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	val, _ := url.QueryUnescape(cookie.Value)
 | 
			
		||||
	return val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCookie creates cookie via given params and value.
 | 
			
		||||
// FIXME: IE support? http://golanghome.com/post/620#reply2
 | 
			
		||||
func NewCookie(name string, value string, others ...interface{}) *http.Cookie {
 | 
			
		||||
	cookie := http.Cookie{}
 | 
			
		||||
	cookie.Name = name
 | 
			
		||||
	cookie.Value = url.QueryEscape(value)
 | 
			
		||||
 | 
			
		||||
	if len(others) > 0 {
 | 
			
		||||
		switch v := others[0].(type) {
 | 
			
		||||
		case int:
 | 
			
		||||
			cookie.MaxAge = v
 | 
			
		||||
		case int64:
 | 
			
		||||
			cookie.MaxAge = int(v)
 | 
			
		||||
		case int32:
 | 
			
		||||
			cookie.MaxAge = int(v)
 | 
			
		||||
		case func(*http.Cookie):
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cookie.Path = "/"
 | 
			
		||||
	if len(others) > 1 {
 | 
			
		||||
		if v, ok := others[1].(string); ok && len(v) > 0 {
 | 
			
		||||
			cookie.Path = v
 | 
			
		||||
		} else if v, ok := others[1].(func(*http.Cookie)); ok {
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(others) > 2 {
 | 
			
		||||
		if v, ok := others[2].(string); ok && len(v) > 0 {
 | 
			
		||||
			cookie.Domain = v
 | 
			
		||||
		} else if v, ok := others[1].(func(*http.Cookie)); ok {
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(others) > 3 {
 | 
			
		||||
		switch v := others[3].(type) {
 | 
			
		||||
		case bool:
 | 
			
		||||
			cookie.Secure = v
 | 
			
		||||
		case func(*http.Cookie):
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		default:
 | 
			
		||||
			if others[3] != nil {
 | 
			
		||||
				cookie.Secure = true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(others) > 4 {
 | 
			
		||||
		if v, ok := others[4].(bool); ok && v {
 | 
			
		||||
			cookie.HttpOnly = true
 | 
			
		||||
		} else if v, ok := others[1].(func(*http.Cookie)); ok {
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(others) > 5 {
 | 
			
		||||
		if v, ok := others[5].(time.Time); ok {
 | 
			
		||||
			cookie.Expires = v
 | 
			
		||||
			cookie.RawExpires = v.Format(time.UnixDate)
 | 
			
		||||
		} else if v, ok := others[1].(func(*http.Cookie)); ok {
 | 
			
		||||
			v(&cookie)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(others) > 6 {
 | 
			
		||||
		for _, other := range others[6:] {
 | 
			
		||||
			if v, ok := other.(func(*http.Cookie)); ok {
 | 
			
		||||
				v(&cookie)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &cookie
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sessioner is a middleware that maps a session.SessionStore service into the Macaron handler chain.
 | 
			
		||||
// An single variadic session.Options struct can be optionally provided to configure.
 | 
			
		||||
func Sessioner(options ...Options) func(next http.Handler) http.Handler {
 | 
			
		||||
	opt := prepareOptions(options)
 | 
			
		||||
	manager, err := NewManager(opt.Provider, opt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	go manager.startGC()
 | 
			
		||||
 | 
			
		||||
	return func(next http.Handler) http.Handler {
 | 
			
		||||
		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
			sess, err := manager.Start(w, req)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic("session(start): " + err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var s = store{
 | 
			
		||||
				RawStore: sess,
 | 
			
		||||
				Manager:  manager,
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			req = req.WithContext(context.WithValue(req.Context(), interface{}("Session"), &s))
 | 
			
		||||
 | 
			
		||||
			next.ServeHTTP(w, req)
 | 
			
		||||
 | 
			
		||||
			if manager.opt.IgnoreReleaseForWebSocket && req.Header.Get("Upgrade") == "websocket" {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err = sess.Release(); err != nil {
 | 
			
		||||
				panic("session(release): " + err.Error())
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSession returns session store
 | 
			
		||||
func GetSession(req *http.Request) Store {
 | 
			
		||||
	sessCtx := req.Context().Value("Session")
 | 
			
		||||
	sess, _ := sessCtx.(*store)
 | 
			
		||||
	return sess
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Provider is the interface that provides session manipulations.
 | 
			
		||||
type Provider interface {
 | 
			
		||||
	// Init initializes session provider.
 | 
			
		||||
	Init(gclifetime int64, config string) error
 | 
			
		||||
	// Read returns raw session store by session ID.
 | 
			
		||||
	Read(sid string) (RawStore, error)
 | 
			
		||||
	// Exist returns true if session with given ID exists.
 | 
			
		||||
	Exist(sid string) bool
 | 
			
		||||
	// Destroy deletes a session by session ID.
 | 
			
		||||
	Destroy(sid string) error
 | 
			
		||||
	// Regenerate regenerates a session store from old session ID to new one.
 | 
			
		||||
	Regenerate(oldsid, sid string) (RawStore, error)
 | 
			
		||||
	// Count counts and returns number of sessions.
 | 
			
		||||
	Count() int
 | 
			
		||||
	// GC calls GC to clean expired sessions.
 | 
			
		||||
	GC()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var providers = make(map[string]Provider)
 | 
			
		||||
 | 
			
		||||
// Register registers a provider.
 | 
			
		||||
func Register(name string, provider Provider) {
 | 
			
		||||
	if provider == nil {
 | 
			
		||||
		panic("session: cannot register provider with nil value")
 | 
			
		||||
	}
 | 
			
		||||
	if _, dup := providers[name]; dup {
 | 
			
		||||
		panic(fmt.Errorf("session: cannot register provider '%s' twice", name))
 | 
			
		||||
	}
 | 
			
		||||
	providers[name] = provider
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//    _____
 | 
			
		||||
//   /     \ _____    ____ _____     ____   ___________
 | 
			
		||||
//  /  \ /  \\__  \  /    \\__  \   / ___\_/ __ \_  __ \
 | 
			
		||||
// /    Y    \/ __ \|   |  \/ __ \_/ /_/  >  ___/|  | \/
 | 
			
		||||
// \____|__  (____  /___|  (____  /\___  / \___  >__|
 | 
			
		||||
//         \/     \/     \/     \//_____/      \/
 | 
			
		||||
 | 
			
		||||
// Manager represents a struct that contains session provider and its configuration.
 | 
			
		||||
type Manager struct {
 | 
			
		||||
	provider Provider
 | 
			
		||||
	opt      Options
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewManager creates and returns a new session manager by given provider name and configuration.
 | 
			
		||||
// It panics when given provider isn't registered.
 | 
			
		||||
func NewManager(name string, opt Options) (*Manager, error) {
 | 
			
		||||
	p, ok := providers[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, fmt.Errorf("session: unknown provider '%s'(forgotten import?)", name)
 | 
			
		||||
	}
 | 
			
		||||
	return &Manager{p, opt}, p.Init(opt.Maxlifetime, opt.ProviderConfig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sessionID generates a new session ID with rand string, unix nano time, remote addr by hash function.
 | 
			
		||||
func (m *Manager) sessionID() string {
 | 
			
		||||
	return hex.EncodeToString(generateRandomKey(m.opt.IDLength / 2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// validSessionID tests whether a provided session ID is a valid session ID.
 | 
			
		||||
func (m *Manager) validSessionID(sid string) (bool, error) {
 | 
			
		||||
	if len(sid) != m.opt.IDLength {
 | 
			
		||||
		return false, fmt.Errorf("invalid 'sid': %s %d != %d", sid, len(sid), m.opt.IDLength)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range sid {
 | 
			
		||||
		switch {
 | 
			
		||||
		case '0' <= sid[i] && sid[i] <= '9':
 | 
			
		||||
		case 'a' <= sid[i] && sid[i] <= 'f':
 | 
			
		||||
		default:
 | 
			
		||||
			return false, errors.New("invalid 'sid': " + sid)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Start starts a session by generating new one
 | 
			
		||||
// or retrieve existence one by reading session ID from HTTP request if it's valid.
 | 
			
		||||
func (m *Manager) Start(resp http.ResponseWriter, req *http.Request) (RawStore, error) {
 | 
			
		||||
	sid := GetCookie(req, m.opt.CookieName)
 | 
			
		||||
	valid, _ := m.validSessionID(sid)
 | 
			
		||||
	if len(sid) > 0 && valid && m.provider.Exist(sid) {
 | 
			
		||||
		return m.provider.Read(sid)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sid = m.sessionID()
 | 
			
		||||
	sess, err := m.provider.Read(sid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cookie := &http.Cookie{
 | 
			
		||||
		Name:     m.opt.CookieName,
 | 
			
		||||
		Value:    sid,
 | 
			
		||||
		Path:     m.opt.CookiePath,
 | 
			
		||||
		HttpOnly: true,
 | 
			
		||||
		Secure:   m.opt.Secure,
 | 
			
		||||
		Domain:   m.opt.Domain,
 | 
			
		||||
		SameSite: m.opt.SameSite,
 | 
			
		||||
	}
 | 
			
		||||
	if m.opt.CookieLifeTime >= 0 {
 | 
			
		||||
		cookie.MaxAge = m.opt.CookieLifeTime
 | 
			
		||||
	}
 | 
			
		||||
	http.SetCookie(resp, cookie)
 | 
			
		||||
	req.AddCookie(cookie)
 | 
			
		||||
	return sess, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read returns raw session store by session ID.
 | 
			
		||||
func (m *Manager) Read(sid string) (RawStore, error) {
 | 
			
		||||
	// Ensure we're trying to read a valid session ID
 | 
			
		||||
	if _, err := m.validSessionID(sid); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m.provider.Read(sid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Destroy deletes a session by given ID.
 | 
			
		||||
func (m *Manager) Destroy(resp http.ResponseWriter, req *http.Request) error {
 | 
			
		||||
	sid := GetCookie(req, m.opt.CookieName)
 | 
			
		||||
	if len(sid) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := m.validSessionID(sid); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := m.provider.Destroy(sid); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	cookie := &http.Cookie{
 | 
			
		||||
		Name:     m.opt.CookieName,
 | 
			
		||||
		Path:     m.opt.CookiePath,
 | 
			
		||||
		HttpOnly: true,
 | 
			
		||||
		Expires:  time.Now(),
 | 
			
		||||
		MaxAge:   -1,
 | 
			
		||||
	}
 | 
			
		||||
	http.SetCookie(resp, cookie)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegenerateID regenerates a session store from old session ID to new one.
 | 
			
		||||
func (m *Manager) RegenerateID(resp http.ResponseWriter, req *http.Request) (sess RawStore, err error) {
 | 
			
		||||
	sid := m.sessionID()
 | 
			
		||||
	oldsid := GetCookie(req, m.opt.CookieName)
 | 
			
		||||
	_, err = m.validSessionID(oldsid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	sess, err = m.provider.Regenerate(oldsid, sid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	cookie := &http.Cookie{
 | 
			
		||||
		Name:     m.opt.CookieName,
 | 
			
		||||
		Value:    sid,
 | 
			
		||||
		Path:     m.opt.CookiePath,
 | 
			
		||||
		HttpOnly: true,
 | 
			
		||||
		Secure:   m.opt.Secure,
 | 
			
		||||
		Domain:   m.opt.Domain,
 | 
			
		||||
		SameSite: m.opt.SameSite,
 | 
			
		||||
	}
 | 
			
		||||
	if m.opt.CookieLifeTime >= 0 {
 | 
			
		||||
		cookie.MaxAge = m.opt.CookieLifeTime
 | 
			
		||||
	}
 | 
			
		||||
	http.SetCookie(resp, cookie)
 | 
			
		||||
	req.AddCookie(cookie)
 | 
			
		||||
	return sess, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count counts and returns number of sessions.
 | 
			
		||||
func (m *Manager) Count() int {
 | 
			
		||||
	return m.provider.Count()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GC starts GC job in a certain period.
 | 
			
		||||
func (m *Manager) GC() {
 | 
			
		||||
	m.provider.GC()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// startGC starts GC job in a certain period.
 | 
			
		||||
func (m *Manager) startGC() {
 | 
			
		||||
	m.GC()
 | 
			
		||||
	time.AfterFunc(time.Duration(m.opt.Gclifetime)*time.Second, func() { m.startGC() })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetSecure indicates whether to set cookie with HTTPS or not.
 | 
			
		||||
func (m *Manager) SetSecure(secure bool) {
 | 
			
		||||
	m.opt.Secure = secure
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								vendor/gitea.com/go-chi/session/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								vendor/gitea.com/go-chi/session/utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
// Copyright 2013 Beego Authors
 | 
			
		||||
// Copyright 2014 The Macaron Authors
 | 
			
		||||
//
 | 
			
		||||
// 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{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EncodeGob encodes obj with gob
 | 
			
		||||
func EncodeGob(obj map[interface{}]interface{}) ([]byte, error) {
 | 
			
		||||
	for _, v := range obj {
 | 
			
		||||
		gob.Register(v)
 | 
			
		||||
	}
 | 
			
		||||
	buf := bytes.NewBuffer(nil)
 | 
			
		||||
	err := gob.NewEncoder(buf).Encode(obj)
 | 
			
		||||
	return buf.Bytes(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeGob decodes bytes to obj
 | 
			
		||||
func DecodeGob(encoded []byte) (out map[interface{}]interface{}, err error) {
 | 
			
		||||
	buf := bytes.NewBuffer(encoded)
 | 
			
		||||
	err = gob.NewDecoder(buf).Decode(&out)
 | 
			
		||||
	return out, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NOTE: A local copy in case of underlying package change
 | 
			
		||||
var alphanum = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
 | 
			
		||||
 | 
			
		||||
// 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, alphanum...)
 | 
			
		||||
	}
 | 
			
		||||
	return k
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user