├── .env ├── .gitignore ├── Gopkg.lock ├── Gopkg.toml ├── README.md ├── controllers └── user.go ├── main.go ├── models ├── exception.go ├── token.go └── user.go ├── routes └── routes.go ├── utils ├── auth │ └── auth.go └── db.go └── vendor ├── github.com ├── dgrijalva │ └── jwt-go │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── MIGRATION_GUIDE.md │ │ ├── README.md │ │ ├── VERSION_HISTORY.md │ │ ├── claims.go │ │ ├── doc.go │ │ ├── ecdsa.go │ │ ├── ecdsa_utils.go │ │ ├── errors.go │ │ ├── hmac.go │ │ ├── map_claims.go │ │ ├── none.go │ │ ├── parser.go │ │ ├── rsa.go │ │ ├── rsa_pss.go │ │ ├── rsa_utils.go │ │ ├── signing_method.go │ │ └── token.go ├── gorilla │ └── mux │ │ ├── .travis.yml │ │ ├── AUTHORS │ │ ├── ISSUE_TEMPLATE.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── context.go │ │ ├── doc.go │ │ ├── go.mod │ │ ├── middleware.go │ │ ├── mux.go │ │ ├── regexp.go │ │ ├── route.go │ │ └── test_helpers.go ├── jinzhu │ ├── gorm │ │ ├── .codeclimate.yml │ │ ├── .gitignore │ │ ├── License │ │ ├── README.md │ │ ├── association.go │ │ ├── callback.go │ │ ├── callback_create.go │ │ ├── callback_delete.go │ │ ├── callback_query.go │ │ ├── callback_query_preload.go │ │ ├── callback_row_query.go │ │ ├── callback_save.go │ │ ├── callback_update.go │ │ ├── dialect.go │ │ ├── dialect_common.go │ │ ├── dialect_mysql.go │ │ ├── dialect_postgres.go │ │ ├── dialect_sqlite3.go │ │ ├── dialects │ │ │ └── postgres │ │ │ │ └── postgres.go │ │ ├── docker-compose.yml │ │ ├── errors.go │ │ ├── field.go │ │ ├── interface.go │ │ ├── join_table_handler.go │ │ ├── logger.go │ │ ├── main.go │ │ ├── model.go │ │ ├── model_struct.go │ │ ├── naming.go │ │ ├── scope.go │ │ ├── search.go │ │ ├── test_all.sh │ │ ├── utils.go │ │ └── wercker.yml │ └── inflection │ │ ├── LICENSE │ │ ├── README.md │ │ ├── inflections.go │ │ └── wercker.yml ├── joho │ └── godotenv │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENCE │ │ ├── README.md │ │ └── godotenv.go └── lib │ └── pq │ ├── .gitignore │ ├── .travis.sh │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE.md │ ├── README.md │ ├── TESTS.md │ ├── array.go │ ├── buf.go │ ├── conn.go │ ├── conn_go18.go │ ├── connector.go │ ├── copy.go │ ├── doc.go │ ├── encode.go │ ├── error.go │ ├── go.mod │ ├── hstore │ └── hstore.go │ ├── notify.go │ ├── oid │ ├── doc.go │ ├── gen.go │ └── types.go │ ├── rows.go │ ├── scram │ └── scram.go │ ├── ssl.go │ ├── ssl_permissions.go │ ├── ssl_windows.go │ ├── url.go │ ├── user_posix.go │ ├── user_windows.go │ └── uuid.go └── golang.org └── x └── crypto ├── AUTHORS ├── CONTRIBUTORS ├── LICENSE ├── PATENTS ├── bcrypt ├── base64.go └── bcrypt.go └── blowfish ├── block.go ├── cipher.go └── const.go /.env: -------------------------------------------------------------------------------- 1 | databaseName = expense 2 | databasePassword = david 3 | databaseUser = david 4 | databaseType = postgres 5 | databaseHost = localhost 6 | databasePort = 5434 7 | PORT = 8080 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:76dc72490af7174349349838f2fe118996381b31ea83243812a97e5a0fd5ed55" 6 | name = "github.com/dgrijalva/jwt-go" 7 | packages = ["."] 8 | pruneopts = "UT" 9 | revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" 10 | version = "v3.2.0" 11 | 12 | [[projects]] 13 | digest = "1:ca59b1175189b3f0e9f1793d2c350114be36eaabbe5b9f554b35edee1de50aea" 14 | name = "github.com/gorilla/mux" 15 | packages = ["."] 16 | pruneopts = "UT" 17 | revision = "a7962380ca08b5a188038c69871b8d3fbdf31e89" 18 | version = "v1.7.0" 19 | 20 | [[projects]] 21 | digest = "1:7e63b12cdd7bef2c411d736cb67e28134d39f5d236aa1bfb8f3d55e3ad709eca" 22 | name = "github.com/jinzhu/gorm" 23 | packages = [ 24 | ".", 25 | "dialects/postgres", 26 | ] 27 | pruneopts = "UT" 28 | revision = "472c70caa40267cb89fd8facb07fe6454b578626" 29 | version = "v1.9.2" 30 | 31 | [[projects]] 32 | branch = "master" 33 | digest = "1:fd97437fbb6b7dce04132cf06775bd258cce305c44add58eb55ca86c6c325160" 34 | name = "github.com/jinzhu/inflection" 35 | packages = ["."] 36 | pruneopts = "UT" 37 | revision = "04140366298a54a039076d798123ffa108fff46c" 38 | 39 | [[projects]] 40 | digest = "1:ecd9aa82687cf31d1585d4ac61d0ba180e42e8a6182b85bd785fcca8dfeefc1b" 41 | name = "github.com/joho/godotenv" 42 | packages = ["."] 43 | pruneopts = "UT" 44 | revision = "23d116af351c84513e1946b527c88823e476be13" 45 | version = "v1.3.0" 46 | 47 | [[projects]] 48 | digest = "1:0e06e487551e2f9e0d6967a15c42223354e37c2e9869b301b14a42e4b51ea3e0" 49 | name = "github.com/lib/pq" 50 | packages = [ 51 | ".", 52 | "hstore", 53 | "oid", 54 | "scram", 55 | ] 56 | pruneopts = "UT" 57 | revision = "bc6a3c0594130b1e34005880bc600b6d3f49fa7f" 58 | version = "v1.1.1" 59 | 60 | [[projects]] 61 | branch = "master" 62 | digest = "1:9d5b5d543996dd584da1db1e0de1926f3e4c3a8dba0fa2f8db70f3ebee2342e0" 63 | name = "golang.org/x/crypto" 64 | packages = [ 65 | "bcrypt", 66 | "blowfish", 67 | ] 68 | pruneopts = "UT" 69 | revision = "8dd112bcdc25174059e45e07517d9fc663123347" 70 | 71 | [solve-meta] 72 | analyzer-name = "dep" 73 | analyzer-version = 1 74 | input-imports = [ 75 | "github.com/dgrijalva/jwt-go", 76 | "github.com/gorilla/mux", 77 | "github.com/jinzhu/gorm", 78 | "github.com/jinzhu/gorm/dialects/postgres", 79 | "github.com/joho/godotenv", 80 | "golang.org/x/crypto/bcrypt", 81 | ] 82 | solver-name = "gps-cdcl" 83 | solver-version = 1 84 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [prune] 29 | go-tests = true 30 | unused-packages = true 31 | 32 | [[constraint]] 33 | name = "github.com/gorilla/mux" 34 | version = "1.7.0" 35 | 36 | [[constraint]] 37 | name = "github.com/dgrijalva/jwt-go" 38 | version = "3.2.0" 39 | 40 | [[constraint]] 41 | name = "github.com/jinzhu/gorm" 42 | version = "1.9.2" 43 | 44 | [[constraint]] 45 | branch = "master" 46 | name = "golang.org/x/crypto" 47 | 48 | [[constraint]] 49 | name = "github.com/joho/godotenv" 50 | version = "1.3.0" 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # golang-authentication 2 | 3 | 4 | To start this app, perform the following step in order 5 | 6 | 1. Clone this repo to your machine 7 | 2. cd into the project folder 8 | 3. enter `go run main.go` to start server 9 | -------------------------------------------------------------------------------- /controllers/user.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "auth/models" 5 | "auth/utils" 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "time" 10 | 11 | jwt "github.com/dgrijalva/jwt-go" 12 | "github.com/gorilla/mux" 13 | "golang.org/x/crypto/bcrypt" 14 | ) 15 | 16 | type ErrorResponse struct { 17 | Err string 18 | } 19 | 20 | type error interface { 21 | Error() string 22 | } 23 | 24 | var db = utils.ConnectDB() 25 | 26 | func MagaAPI(w http.ResponseWriter, r *http.Request) { 27 | fmt.Println("i am here") 28 | } 29 | 30 | func TestAPI(w http.ResponseWriter, r *http.Request) { 31 | w.Write([]byte("API live and kicking")) 32 | } 33 | 34 | func Login(w http.ResponseWriter, r *http.Request) { 35 | user := &models.User{} 36 | err := json.NewDecoder(r.Body).Decode(user) 37 | if err != nil { 38 | var resp = map[string]interface{}{"status": false, "message": "Invalid request"} 39 | json.NewEncoder(w).Encode(resp) 40 | return 41 | } 42 | resp := FindOne(user.Email, user.Password) 43 | json.NewEncoder(w).Encode(resp) 44 | } 45 | 46 | func FindOne(email, password string) map[string]interface{} { 47 | user := &models.User{} 48 | 49 | if err := db.Where("Email = ?", email).First(user).Error; err != nil { 50 | var resp = map[string]interface{}{"status": false, "message": "Email address not found"} 51 | return resp 52 | } 53 | expiresAt := time.Now().Add(time.Minute * 100000).Unix() 54 | 55 | errf := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) 56 | if errf != nil && errf == bcrypt.ErrMismatchedHashAndPassword { //Password does not match! 57 | var resp = map[string]interface{}{"status": false, "message": "Invalid login credentials. Please try again"} 58 | return resp 59 | } 60 | 61 | tk := &models.Token{ 62 | UserID: user.ID, 63 | Name: user.Name, 64 | Email: user.Email, 65 | StandardClaims: &jwt.StandardClaims{ 66 | ExpiresAt: expiresAt, 67 | }, 68 | } 69 | 70 | token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), tk) 71 | 72 | tokenString, error := token.SignedString([]byte("secret")) 73 | if error != nil { 74 | fmt.Println(error) 75 | } 76 | 77 | var resp = map[string]interface{}{"status": false, "message": "logged in"} 78 | resp["token"] = tokenString //Store the token in the response 79 | resp["user"] = user 80 | return resp 81 | } 82 | 83 | //CreateUser function -- create a new user 84 | func CreateUser(w http.ResponseWriter, r *http.Request) { 85 | 86 | user := &models.User{} 87 | json.NewDecoder(r.Body).Decode(user) 88 | 89 | pass, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) 90 | if err != nil { 91 | fmt.Println(err) 92 | err := ErrorResponse{ 93 | Err: "Password Encryption failed", 94 | } 95 | json.NewEncoder(w).Encode(err) 96 | } 97 | 98 | user.Password = string(pass) 99 | 100 | createdUser := db.Create(user) 101 | var errMessage = createdUser.Error 102 | 103 | if createdUser.Error != nil { 104 | fmt.Println(errMessage) 105 | } 106 | json.NewEncoder(w).Encode(createdUser) 107 | } 108 | 109 | //FetchUser function 110 | func FetchUsers(w http.ResponseWriter, r *http.Request) { 111 | var users []models.User 112 | db.Preload("auths").Find(&users) 113 | 114 | json.NewEncoder(w).Encode(users) 115 | } 116 | 117 | func UpdateUser(w http.ResponseWriter, r *http.Request) { 118 | user := &models.User{} 119 | params := mux.Vars(r) 120 | var id = params["id"] 121 | db.First(&user, id) 122 | json.NewDecoder(r.Body).Decode(user) 123 | db.Save(&user) 124 | json.NewEncoder(w).Encode(&user) 125 | } 126 | 127 | func DeleteUser(w http.ResponseWriter, r *http.Request) { 128 | params := mux.Vars(r) 129 | var id = params["id"] 130 | var user models.User 131 | db.First(&user, id) 132 | db.Delete(&user) 133 | json.NewEncoder(w).Encode("User deleted") 134 | } 135 | 136 | func GetUser(w http.ResponseWriter, r *http.Request) { 137 | params := mux.Vars(r) 138 | var id = params["id"] 139 | var user models.User 140 | db.First(&user, id) 141 | json.NewEncoder(w).Encode(&user) 142 | } 143 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "auth/routes" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "os" 9 | 10 | "github.com/joho/godotenv" 11 | ) 12 | 13 | func main() { 14 | e := godotenv.Load() 15 | 16 | if e != nil { 17 | log.Fatal("Error loading .env file") 18 | } 19 | fmt.Println(e) 20 | 21 | port := os.Getenv("PORT") 22 | 23 | // Handle routes 24 | http.Handle("/", routes.Handlers()) 25 | 26 | // serve 27 | log.Printf("Server up on port '%s'", port) 28 | log.Fatal(http.ListenAndServe(":"+port, nil)) 29 | } 30 | -------------------------------------------------------------------------------- /models/exception.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //Exception struct declaration 4 | type Exception struct { 5 | Message string `json:"message"` 6 | } 7 | -------------------------------------------------------------------------------- /models/token.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import jwt "github.com/dgrijalva/jwt-go" 4 | 5 | //Token struct declaration 6 | type Token struct { 7 | UserID uint 8 | Name string 9 | Email string 10 | *jwt.StandardClaims 11 | } 12 | -------------------------------------------------------------------------------- /models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/jinzhu/gorm" 5 | ) 6 | 7 | //User struct declaration 8 | type User struct { 9 | gorm.Model 10 | 11 | Name string 12 | Email string `gorm:"type:varchar(100);unique_index"` 13 | Gender string `json:"Gender"` 14 | Password string `json:"Password"` 15 | } 16 | -------------------------------------------------------------------------------- /routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "auth/controllers" 5 | "auth/utils/auth" 6 | "net/http" 7 | 8 | "github.com/gorilla/mux" 9 | ) 10 | 11 | func Handlers() *mux.Router { 12 | 13 | r := mux.NewRouter().StrictSlash(true) 14 | r.Use(CommonMiddleware) 15 | 16 | r.HandleFunc("/", controllers.TestAPI).Methods("GET") 17 | r.HandleFunc("/api", controllers.TestAPI).Methods("GET") 18 | r.HandleFunc("/register", controllers.CreateUser).Methods("POST") 19 | r.HandleFunc("/login", controllers.Login).Methods("POST") 20 | 21 | // Auth route 22 | s := r.PathPrefix("/auth").Subrouter() 23 | s.Use(auth.JwtVerify) 24 | s.HandleFunc("/user", controllers.FetchUsers).Methods("GET") 25 | s.HandleFunc("/user/{id}", controllers.GetUser).Methods("GET") 26 | s.HandleFunc("/user/{id}", controllers.UpdateUser).Methods("PUT") 27 | s.HandleFunc("/user/{id}", controllers.DeleteUser).Methods("DELETE") 28 | return r 29 | } 30 | 31 | // CommonMiddleware --Set content-type 32 | func CommonMiddleware(next http.Handler) http.Handler { 33 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 34 | w.Header().Add("Content-Type", "application/json") 35 | w.Header().Set("Access-Control-Allow-Origin", "*") 36 | w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") 37 | w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, Access-Control-Request-Headers, Access-Control-Request-Method, Connection, Host, Origin, User-Agent, Referer, Cache-Control, X-header") 38 | next.ServeHTTP(w, r) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /utils/auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "auth/models" 5 | "context" 6 | "encoding/json" 7 | "net/http" 8 | "strings" 9 | 10 | jwt "github.com/dgrijalva/jwt-go" 11 | ) 12 | 13 | //Exception struct 14 | type Exception models.Exception 15 | 16 | // JwtVerify Middleware function 17 | func JwtVerify(next http.Handler) http.Handler { 18 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 19 | 20 | var header = r.Header.Get("x-access-token") //Grab the token from the header 21 | 22 | header = strings.TrimSpace(header) 23 | 24 | if header == "" { 25 | //Token is missing, returns with error code 403 Unauthorized 26 | w.WriteHeader(http.StatusForbidden) 27 | json.NewEncoder(w).Encode(Exception{Message: "Missing auth token"}) 28 | return 29 | } 30 | tk := &models.Token{} 31 | 32 | _, err := jwt.ParseWithClaims(header, tk, func(token *jwt.Token) (interface{}, error) { 33 | return []byte("secret"), nil 34 | }) 35 | 36 | if err != nil { 37 | w.WriteHeader(http.StatusForbidden) 38 | json.NewEncoder(w).Encode(Exception{Message: err.Error()}) 39 | return 40 | } 41 | 42 | ctx := context.WithValue(r.Context(), "user", tk) 43 | next.ServeHTTP(w, r.WithContext(ctx)) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /utils/db.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "auth/models" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | "github.com/jinzhu/gorm" 10 | _ "github.com/jinzhu/gorm/dialects/postgres" //Gorm postgres dialect interface 11 | "github.com/joho/godotenv" 12 | ) 13 | 14 | //ConnectDB function: Make database connection 15 | func ConnectDB() *gorm.DB { 16 | 17 | //Load environmenatal variables 18 | err := godotenv.Load() 19 | 20 | if err != nil { 21 | log.Fatal("Error loading .env file") 22 | } 23 | 24 | username := os.Getenv("databaseUser") 25 | password := os.Getenv("databasePassword") 26 | databaseName := os.Getenv("databaseName") 27 | databaseHost := os.Getenv("databaseHost") 28 | 29 | //Define DB connection string 30 | dbURI := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s", databaseHost, username, databaseName, password) 31 | 32 | //connect to db URI 33 | db, err := gorm.Open("postgres", dbURI) 34 | 35 | if err != nil { 36 | fmt.Println("error", err) 37 | panic(err) 38 | } 39 | // close db when not in use 40 | // defer db.Close() 41 | 42 | // Migrate the schema 43 | db.AutoMigrate( 44 | &models.User{}) 45 | 46 | fmt.Println("Successfully connected!", db) 47 | return db 48 | } 49 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin 3 | 4 | 5 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | script: 4 | - go vet ./... 5 | - go test -v ./... 6 | 7 | go: 8 | - 1.3 9 | - 1.4 10 | - 1.5 11 | - 1.6 12 | - 1.7 13 | - tip 14 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Dave Grijalva 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md: -------------------------------------------------------------------------------- 1 | ## Migration Guide from v2 -> v3 2 | 3 | Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. 4 | 5 | ### `Token.Claims` is now an interface type 6 | 7 | The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. 8 | 9 | `MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. 10 | 11 | The old example for parsing a token looked like this.. 12 | 13 | ```go 14 | if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { 15 | fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) 16 | } 17 | ``` 18 | 19 | is now directly mapped to... 20 | 21 | ```go 22 | if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { 23 | claims := token.Claims.(jwt.MapClaims) 24 | fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) 25 | } 26 | ``` 27 | 28 | `StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. 29 | 30 | ```go 31 | type MyCustomClaims struct { 32 | User string 33 | *StandardClaims 34 | } 35 | 36 | if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { 37 | claims := token.Claims.(*MyCustomClaims) 38 | fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) 39 | } 40 | ``` 41 | 42 | ### `ParseFromRequest` has been moved 43 | 44 | To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. 45 | 46 | `Extractors` do the work of picking the token string out of a request. The interface is simple and composable. 47 | 48 | This simple parsing example: 49 | 50 | ```go 51 | if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { 52 | fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) 53 | } 54 | ``` 55 | 56 | is directly mapped to: 57 | 58 | ```go 59 | if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { 60 | claims := token.Claims.(jwt.MapClaims) 61 | fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) 62 | } 63 | ``` 64 | 65 | There are several concrete `Extractor` types provided for your convenience: 66 | 67 | * `HeaderExtractor` will search a list of headers until one contains content. 68 | * `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. 69 | * `MultiExtractor` will try a list of `Extractors` in order until one returns content. 70 | * `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. 71 | * `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument 72 | * `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header 73 | 74 | 75 | ### RSA signing methods no longer accept `[]byte` keys 76 | 77 | Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. 78 | 79 | To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. 80 | 81 | ```go 82 | func keyLookupFunc(*Token) (interface{}, error) { 83 | // Don't forget to validate the alg is what you expect: 84 | if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { 85 | return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) 86 | } 87 | 88 | // Look up key 89 | key, err := lookupPublicKey(token.Header["kid"]) 90 | if err != nil { 91 | return nil, err 92 | } 93 | 94 | // Unpack key from PEM encoded PKCS8 95 | return jwt.ParseRSAPublicKeyFromPEM(key) 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/claims.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/subtle" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // For a type to be a Claims object, it must just have a Valid method that determines 10 | // if the token is invalid for any supported reason 11 | type Claims interface { 12 | Valid() error 13 | } 14 | 15 | // Structured version of Claims Section, as referenced at 16 | // https://tools.ietf.org/html/rfc7519#section-4.1 17 | // See examples for how to use this with your own claim types 18 | type StandardClaims struct { 19 | Audience string `json:"aud,omitempty"` 20 | ExpiresAt int64 `json:"exp,omitempty"` 21 | Id string `json:"jti,omitempty"` 22 | IssuedAt int64 `json:"iat,omitempty"` 23 | Issuer string `json:"iss,omitempty"` 24 | NotBefore int64 `json:"nbf,omitempty"` 25 | Subject string `json:"sub,omitempty"` 26 | } 27 | 28 | // Validates time based claims "exp, iat, nbf". 29 | // There is no accounting for clock skew. 30 | // As well, if any of the above claims are not in the token, it will still 31 | // be considered a valid claim. 32 | func (c StandardClaims) Valid() error { 33 | vErr := new(ValidationError) 34 | now := TimeFunc().Unix() 35 | 36 | // The claims below are optional, by default, so if they are set to the 37 | // default value in Go, let's not fail the verification for them. 38 | if c.VerifyExpiresAt(now, false) == false { 39 | delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) 40 | vErr.Inner = fmt.Errorf("token is expired by %v", delta) 41 | vErr.Errors |= ValidationErrorExpired 42 | } 43 | 44 | if c.VerifyIssuedAt(now, false) == false { 45 | vErr.Inner = fmt.Errorf("Token used before issued") 46 | vErr.Errors |= ValidationErrorIssuedAt 47 | } 48 | 49 | if c.VerifyNotBefore(now, false) == false { 50 | vErr.Inner = fmt.Errorf("token is not valid yet") 51 | vErr.Errors |= ValidationErrorNotValidYet 52 | } 53 | 54 | if vErr.valid() { 55 | return nil 56 | } 57 | 58 | return vErr 59 | } 60 | 61 | // Compares the aud claim against cmp. 62 | // If required is false, this method will return true if the value matches or is unset 63 | func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { 64 | return verifyAud(c.Audience, cmp, req) 65 | } 66 | 67 | // Compares the exp claim against cmp. 68 | // If required is false, this method will return true if the value matches or is unset 69 | func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { 70 | return verifyExp(c.ExpiresAt, cmp, req) 71 | } 72 | 73 | // Compares the iat claim against cmp. 74 | // If required is false, this method will return true if the value matches or is unset 75 | func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { 76 | return verifyIat(c.IssuedAt, cmp, req) 77 | } 78 | 79 | // Compares the iss claim against cmp. 80 | // If required is false, this method will return true if the value matches or is unset 81 | func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { 82 | return verifyIss(c.Issuer, cmp, req) 83 | } 84 | 85 | // Compares the nbf claim against cmp. 86 | // If required is false, this method will return true if the value matches or is unset 87 | func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { 88 | return verifyNbf(c.NotBefore, cmp, req) 89 | } 90 | 91 | // ----- helpers 92 | 93 | func verifyAud(aud string, cmp string, required bool) bool { 94 | if aud == "" { 95 | return !required 96 | } 97 | if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 { 98 | return true 99 | } else { 100 | return false 101 | } 102 | } 103 | 104 | func verifyExp(exp int64, now int64, required bool) bool { 105 | if exp == 0 { 106 | return !required 107 | } 108 | return now <= exp 109 | } 110 | 111 | func verifyIat(iat int64, now int64, required bool) bool { 112 | if iat == 0 { 113 | return !required 114 | } 115 | return now >= iat 116 | } 117 | 118 | func verifyIss(iss string, cmp string, required bool) bool { 119 | if iss == "" { 120 | return !required 121 | } 122 | if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 { 123 | return true 124 | } else { 125 | return false 126 | } 127 | } 128 | 129 | func verifyNbf(nbf int64, now int64, required bool) bool { 130 | if nbf == 0 { 131 | return !required 132 | } 133 | return now >= nbf 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/doc.go: -------------------------------------------------------------------------------- 1 | // Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html 2 | // 3 | // See README.md for more info. 4 | package jwt 5 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/ecdsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/rand" 7 | "errors" 8 | "math/big" 9 | ) 10 | 11 | var ( 12 | // Sadly this is missing from crypto/ecdsa compared to crypto/rsa 13 | ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") 14 | ) 15 | 16 | // Implements the ECDSA family of signing methods signing methods 17 | // Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification 18 | type SigningMethodECDSA struct { 19 | Name string 20 | Hash crypto.Hash 21 | KeySize int 22 | CurveBits int 23 | } 24 | 25 | // Specific instances for EC256 and company 26 | var ( 27 | SigningMethodES256 *SigningMethodECDSA 28 | SigningMethodES384 *SigningMethodECDSA 29 | SigningMethodES512 *SigningMethodECDSA 30 | ) 31 | 32 | func init() { 33 | // ES256 34 | SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} 35 | RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { 36 | return SigningMethodES256 37 | }) 38 | 39 | // ES384 40 | SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} 41 | RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { 42 | return SigningMethodES384 43 | }) 44 | 45 | // ES512 46 | SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} 47 | RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { 48 | return SigningMethodES512 49 | }) 50 | } 51 | 52 | func (m *SigningMethodECDSA) Alg() string { 53 | return m.Name 54 | } 55 | 56 | // Implements the Verify method from SigningMethod 57 | // For this verify method, key must be an ecdsa.PublicKey struct 58 | func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { 59 | var err error 60 | 61 | // Decode the signature 62 | var sig []byte 63 | if sig, err = DecodeSegment(signature); err != nil { 64 | return err 65 | } 66 | 67 | // Get the key 68 | var ecdsaKey *ecdsa.PublicKey 69 | switch k := key.(type) { 70 | case *ecdsa.PublicKey: 71 | ecdsaKey = k 72 | default: 73 | return ErrInvalidKeyType 74 | } 75 | 76 | if len(sig) != 2*m.KeySize { 77 | return ErrECDSAVerification 78 | } 79 | 80 | r := big.NewInt(0).SetBytes(sig[:m.KeySize]) 81 | s := big.NewInt(0).SetBytes(sig[m.KeySize:]) 82 | 83 | // Create hasher 84 | if !m.Hash.Available() { 85 | return ErrHashUnavailable 86 | } 87 | hasher := m.Hash.New() 88 | hasher.Write([]byte(signingString)) 89 | 90 | // Verify the signature 91 | if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true { 92 | return nil 93 | } else { 94 | return ErrECDSAVerification 95 | } 96 | } 97 | 98 | // Implements the Sign method from SigningMethod 99 | // For this signing method, key must be an ecdsa.PrivateKey struct 100 | func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { 101 | // Get the key 102 | var ecdsaKey *ecdsa.PrivateKey 103 | switch k := key.(type) { 104 | case *ecdsa.PrivateKey: 105 | ecdsaKey = k 106 | default: 107 | return "", ErrInvalidKeyType 108 | } 109 | 110 | // Create the hasher 111 | if !m.Hash.Available() { 112 | return "", ErrHashUnavailable 113 | } 114 | 115 | hasher := m.Hash.New() 116 | hasher.Write([]byte(signingString)) 117 | 118 | // Sign the string and return r, s 119 | if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { 120 | curveBits := ecdsaKey.Curve.Params().BitSize 121 | 122 | if m.CurveBits != curveBits { 123 | return "", ErrInvalidKey 124 | } 125 | 126 | keyBytes := curveBits / 8 127 | if curveBits%8 > 0 { 128 | keyBytes += 1 129 | } 130 | 131 | // We serialize the outpus (r and s) into big-endian byte arrays and pad 132 | // them with zeros on the left to make sure the sizes work out. Both arrays 133 | // must be keyBytes long, and the output must be 2*keyBytes long. 134 | rBytes := r.Bytes() 135 | rBytesPadded := make([]byte, keyBytes) 136 | copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) 137 | 138 | sBytes := s.Bytes() 139 | sBytesPadded := make([]byte, keyBytes) 140 | copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) 141 | 142 | out := append(rBytesPadded, sBytesPadded...) 143 | 144 | return EncodeSegment(out), nil 145 | } else { 146 | return "", err 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key") 12 | ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key") 13 | ) 14 | 15 | // Parse PEM encoded Elliptic Curve Private Key Structure 16 | func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { 17 | var err error 18 | 19 | // Parse PEM block 20 | var block *pem.Block 21 | if block, _ = pem.Decode(key); block == nil { 22 | return nil, ErrKeyMustBePEMEncoded 23 | } 24 | 25 | // Parse the key 26 | var parsedKey interface{} 27 | if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { 28 | return nil, err 29 | } 30 | 31 | var pkey *ecdsa.PrivateKey 32 | var ok bool 33 | if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { 34 | return nil, ErrNotECPrivateKey 35 | } 36 | 37 | return pkey, nil 38 | } 39 | 40 | // Parse PEM encoded PKCS1 or PKCS8 public key 41 | func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { 42 | var err error 43 | 44 | // Parse PEM block 45 | var block *pem.Block 46 | if block, _ = pem.Decode(key); block == nil { 47 | return nil, ErrKeyMustBePEMEncoded 48 | } 49 | 50 | // Parse the key 51 | var parsedKey interface{} 52 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 53 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 54 | parsedKey = cert.PublicKey 55 | } else { 56 | return nil, err 57 | } 58 | } 59 | 60 | var pkey *ecdsa.PublicKey 61 | var ok bool 62 | if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { 63 | return nil, ErrNotECPublicKey 64 | } 65 | 66 | return pkey, nil 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/errors.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // Error constants 8 | var ( 9 | ErrInvalidKey = errors.New("key is invalid") 10 | ErrInvalidKeyType = errors.New("key is of invalid type") 11 | ErrHashUnavailable = errors.New("the requested hash function is unavailable") 12 | ) 13 | 14 | // The errors that might occur when parsing and validating a token 15 | const ( 16 | ValidationErrorMalformed uint32 = 1 << iota // Token is malformed 17 | ValidationErrorUnverifiable // Token could not be verified because of signing problems 18 | ValidationErrorSignatureInvalid // Signature validation failed 19 | 20 | // Standard Claim validation errors 21 | ValidationErrorAudience // AUD validation failed 22 | ValidationErrorExpired // EXP validation failed 23 | ValidationErrorIssuedAt // IAT validation failed 24 | ValidationErrorIssuer // ISS validation failed 25 | ValidationErrorNotValidYet // NBF validation failed 26 | ValidationErrorId // JTI validation failed 27 | ValidationErrorClaimsInvalid // Generic claims validation error 28 | ) 29 | 30 | // Helper for constructing a ValidationError with a string error message 31 | func NewValidationError(errorText string, errorFlags uint32) *ValidationError { 32 | return &ValidationError{ 33 | text: errorText, 34 | Errors: errorFlags, 35 | } 36 | } 37 | 38 | // The error from Parse if token is not valid 39 | type ValidationError struct { 40 | Inner error // stores the error returned by external dependencies, i.e.: KeyFunc 41 | Errors uint32 // bitfield. see ValidationError... constants 42 | text string // errors that do not have a valid error just have text 43 | } 44 | 45 | // Validation error is an error type 46 | func (e ValidationError) Error() string { 47 | if e.Inner != nil { 48 | return e.Inner.Error() 49 | } else if e.text != "" { 50 | return e.text 51 | } else { 52 | return "token is invalid" 53 | } 54 | } 55 | 56 | // No errors 57 | func (e *ValidationError) valid() bool { 58 | return e.Errors == 0 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/hmac.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/hmac" 6 | "errors" 7 | ) 8 | 9 | // Implements the HMAC-SHA family of signing methods signing methods 10 | // Expects key type of []byte for both signing and validation 11 | type SigningMethodHMAC struct { 12 | Name string 13 | Hash crypto.Hash 14 | } 15 | 16 | // Specific instances for HS256 and company 17 | var ( 18 | SigningMethodHS256 *SigningMethodHMAC 19 | SigningMethodHS384 *SigningMethodHMAC 20 | SigningMethodHS512 *SigningMethodHMAC 21 | ErrSignatureInvalid = errors.New("signature is invalid") 22 | ) 23 | 24 | func init() { 25 | // HS256 26 | SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} 27 | RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { 28 | return SigningMethodHS256 29 | }) 30 | 31 | // HS384 32 | SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} 33 | RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { 34 | return SigningMethodHS384 35 | }) 36 | 37 | // HS512 38 | SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} 39 | RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { 40 | return SigningMethodHS512 41 | }) 42 | } 43 | 44 | func (m *SigningMethodHMAC) Alg() string { 45 | return m.Name 46 | } 47 | 48 | // Verify the signature of HSXXX tokens. Returns nil if the signature is valid. 49 | func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { 50 | // Verify the key is the right type 51 | keyBytes, ok := key.([]byte) 52 | if !ok { 53 | return ErrInvalidKeyType 54 | } 55 | 56 | // Decode signature, for comparison 57 | sig, err := DecodeSegment(signature) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | // Can we use the specified hashing method? 63 | if !m.Hash.Available() { 64 | return ErrHashUnavailable 65 | } 66 | 67 | // This signing method is symmetric, so we validate the signature 68 | // by reproducing the signature from the signing string and key, then 69 | // comparing that against the provided signature. 70 | hasher := hmac.New(m.Hash.New, keyBytes) 71 | hasher.Write([]byte(signingString)) 72 | if !hmac.Equal(sig, hasher.Sum(nil)) { 73 | return ErrSignatureInvalid 74 | } 75 | 76 | // No validation errors. Signature is good. 77 | return nil 78 | } 79 | 80 | // Implements the Sign method from SigningMethod for this signing method. 81 | // Key must be []byte 82 | func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { 83 | if keyBytes, ok := key.([]byte); ok { 84 | if !m.Hash.Available() { 85 | return "", ErrHashUnavailable 86 | } 87 | 88 | hasher := hmac.New(m.Hash.New, keyBytes) 89 | hasher.Write([]byte(signingString)) 90 | 91 | return EncodeSegment(hasher.Sum(nil)), nil 92 | } 93 | 94 | return "", ErrInvalidKeyType 95 | } 96 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/map_claims.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | // "fmt" 7 | ) 8 | 9 | // Claims type that uses the map[string]interface{} for JSON decoding 10 | // This is the default claims type if you don't supply one 11 | type MapClaims map[string]interface{} 12 | 13 | // Compares the aud claim against cmp. 14 | // If required is false, this method will return true if the value matches or is unset 15 | func (m MapClaims) VerifyAudience(cmp string, req bool) bool { 16 | aud, _ := m["aud"].(string) 17 | return verifyAud(aud, cmp, req) 18 | } 19 | 20 | // Compares the exp claim against cmp. 21 | // If required is false, this method will return true if the value matches or is unset 22 | func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { 23 | switch exp := m["exp"].(type) { 24 | case float64: 25 | return verifyExp(int64(exp), cmp, req) 26 | case json.Number: 27 | v, _ := exp.Int64() 28 | return verifyExp(v, cmp, req) 29 | } 30 | return req == false 31 | } 32 | 33 | // Compares the iat claim against cmp. 34 | // If required is false, this method will return true if the value matches or is unset 35 | func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { 36 | switch iat := m["iat"].(type) { 37 | case float64: 38 | return verifyIat(int64(iat), cmp, req) 39 | case json.Number: 40 | v, _ := iat.Int64() 41 | return verifyIat(v, cmp, req) 42 | } 43 | return req == false 44 | } 45 | 46 | // Compares the iss claim against cmp. 47 | // If required is false, this method will return true if the value matches or is unset 48 | func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { 49 | iss, _ := m["iss"].(string) 50 | return verifyIss(iss, cmp, req) 51 | } 52 | 53 | // Compares the nbf claim against cmp. 54 | // If required is false, this method will return true if the value matches or is unset 55 | func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { 56 | switch nbf := m["nbf"].(type) { 57 | case float64: 58 | return verifyNbf(int64(nbf), cmp, req) 59 | case json.Number: 60 | v, _ := nbf.Int64() 61 | return verifyNbf(v, cmp, req) 62 | } 63 | return req == false 64 | } 65 | 66 | // Validates time based claims "exp, iat, nbf". 67 | // There is no accounting for clock skew. 68 | // As well, if any of the above claims are not in the token, it will still 69 | // be considered a valid claim. 70 | func (m MapClaims) Valid() error { 71 | vErr := new(ValidationError) 72 | now := TimeFunc().Unix() 73 | 74 | if m.VerifyExpiresAt(now, false) == false { 75 | vErr.Inner = errors.New("Token is expired") 76 | vErr.Errors |= ValidationErrorExpired 77 | } 78 | 79 | if m.VerifyIssuedAt(now, false) == false { 80 | vErr.Inner = errors.New("Token used before issued") 81 | vErr.Errors |= ValidationErrorIssuedAt 82 | } 83 | 84 | if m.VerifyNotBefore(now, false) == false { 85 | vErr.Inner = errors.New("Token is not valid yet") 86 | vErr.Errors |= ValidationErrorNotValidYet 87 | } 88 | 89 | if vErr.valid() { 90 | return nil 91 | } 92 | 93 | return vErr 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/none.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | // Implements the none signing method. This is required by the spec 4 | // but you probably should never use it. 5 | var SigningMethodNone *signingMethodNone 6 | 7 | const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" 8 | 9 | var NoneSignatureTypeDisallowedError error 10 | 11 | type signingMethodNone struct{} 12 | type unsafeNoneMagicConstant string 13 | 14 | func init() { 15 | SigningMethodNone = &signingMethodNone{} 16 | NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) 17 | 18 | RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { 19 | return SigningMethodNone 20 | }) 21 | } 22 | 23 | func (m *signingMethodNone) Alg() string { 24 | return "none" 25 | } 26 | 27 | // Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key 28 | func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { 29 | // Key must be UnsafeAllowNoneSignatureType to prevent accidentally 30 | // accepting 'none' signing method 31 | if _, ok := key.(unsafeNoneMagicConstant); !ok { 32 | return NoneSignatureTypeDisallowedError 33 | } 34 | // If signing method is none, signature must be an empty string 35 | if signature != "" { 36 | return NewValidationError( 37 | "'none' signing method with non-empty signature", 38 | ValidationErrorSignatureInvalid, 39 | ) 40 | } 41 | 42 | // Accept 'none' signing method. 43 | return nil 44 | } 45 | 46 | // Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key 47 | func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { 48 | if _, ok := key.(unsafeNoneMagicConstant); ok { 49 | return "", nil 50 | } 51 | return "", NoneSignatureTypeDisallowedError 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/parser.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | type Parser struct { 11 | ValidMethods []string // If populated, only these methods will be considered valid 12 | UseJSONNumber bool // Use JSON Number format in JSON decoder 13 | SkipClaimsValidation bool // Skip claims validation during token parsing 14 | } 15 | 16 | // Parse, validate, and return a token. 17 | // keyFunc will receive the parsed token and should return the key for validating. 18 | // If everything is kosher, err will be nil 19 | func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { 20 | return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) 21 | } 22 | 23 | func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { 24 | token, parts, err := p.ParseUnverified(tokenString, claims) 25 | if err != nil { 26 | return token, err 27 | } 28 | 29 | // Verify signing method is in the required set 30 | if p.ValidMethods != nil { 31 | var signingMethodValid = false 32 | var alg = token.Method.Alg() 33 | for _, m := range p.ValidMethods { 34 | if m == alg { 35 | signingMethodValid = true 36 | break 37 | } 38 | } 39 | if !signingMethodValid { 40 | // signing method is not in the listed set 41 | return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) 42 | } 43 | } 44 | 45 | // Lookup key 46 | var key interface{} 47 | if keyFunc == nil { 48 | // keyFunc was not provided. short circuiting validation 49 | return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) 50 | } 51 | if key, err = keyFunc(token); err != nil { 52 | // keyFunc returned an error 53 | if ve, ok := err.(*ValidationError); ok { 54 | return token, ve 55 | } 56 | return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} 57 | } 58 | 59 | vErr := &ValidationError{} 60 | 61 | // Validate Claims 62 | if !p.SkipClaimsValidation { 63 | if err := token.Claims.Valid(); err != nil { 64 | 65 | // If the Claims Valid returned an error, check if it is a validation error, 66 | // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set 67 | if e, ok := err.(*ValidationError); !ok { 68 | vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} 69 | } else { 70 | vErr = e 71 | } 72 | } 73 | } 74 | 75 | // Perform validation 76 | token.Signature = parts[2] 77 | if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { 78 | vErr.Inner = err 79 | vErr.Errors |= ValidationErrorSignatureInvalid 80 | } 81 | 82 | if vErr.valid() { 83 | token.Valid = true 84 | return token, nil 85 | } 86 | 87 | return token, vErr 88 | } 89 | 90 | // WARNING: Don't use this method unless you know what you're doing 91 | // 92 | // This method parses the token but doesn't validate the signature. It's only 93 | // ever useful in cases where you know the signature is valid (because it has 94 | // been checked previously in the stack) and you want to extract values from 95 | // it. 96 | func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { 97 | parts = strings.Split(tokenString, ".") 98 | if len(parts) != 3 { 99 | return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) 100 | } 101 | 102 | token = &Token{Raw: tokenString} 103 | 104 | // parse Header 105 | var headerBytes []byte 106 | if headerBytes, err = DecodeSegment(parts[0]); err != nil { 107 | if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { 108 | return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) 109 | } 110 | return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 111 | } 112 | if err = json.Unmarshal(headerBytes, &token.Header); err != nil { 113 | return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 114 | } 115 | 116 | // parse Claims 117 | var claimBytes []byte 118 | token.Claims = claims 119 | 120 | if claimBytes, err = DecodeSegment(parts[1]); err != nil { 121 | return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 122 | } 123 | dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) 124 | if p.UseJSONNumber { 125 | dec.UseNumber() 126 | } 127 | // JSON Decode. Special case for map type to avoid weird pointer behavior 128 | if c, ok := token.Claims.(MapClaims); ok { 129 | err = dec.Decode(&c) 130 | } else { 131 | err = dec.Decode(&claims) 132 | } 133 | // Handle decode error 134 | if err != nil { 135 | return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 136 | } 137 | 138 | // Lookup signature method 139 | if method, ok := token.Header["alg"].(string); ok { 140 | if token.Method = GetSigningMethod(method); token.Method == nil { 141 | return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) 142 | } 143 | } else { 144 | return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) 145 | } 146 | 147 | return token, parts, nil 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | ) 8 | 9 | // Implements the RSA family of signing methods signing methods 10 | // Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation 11 | type SigningMethodRSA struct { 12 | Name string 13 | Hash crypto.Hash 14 | } 15 | 16 | // Specific instances for RS256 and company 17 | var ( 18 | SigningMethodRS256 *SigningMethodRSA 19 | SigningMethodRS384 *SigningMethodRSA 20 | SigningMethodRS512 *SigningMethodRSA 21 | ) 22 | 23 | func init() { 24 | // RS256 25 | SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} 26 | RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { 27 | return SigningMethodRS256 28 | }) 29 | 30 | // RS384 31 | SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} 32 | RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { 33 | return SigningMethodRS384 34 | }) 35 | 36 | // RS512 37 | SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} 38 | RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { 39 | return SigningMethodRS512 40 | }) 41 | } 42 | 43 | func (m *SigningMethodRSA) Alg() string { 44 | return m.Name 45 | } 46 | 47 | // Implements the Verify method from SigningMethod 48 | // For this signing method, must be an *rsa.PublicKey structure. 49 | func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { 50 | var err error 51 | 52 | // Decode the signature 53 | var sig []byte 54 | if sig, err = DecodeSegment(signature); err != nil { 55 | return err 56 | } 57 | 58 | var rsaKey *rsa.PublicKey 59 | var ok bool 60 | 61 | if rsaKey, ok = key.(*rsa.PublicKey); !ok { 62 | return ErrInvalidKeyType 63 | } 64 | 65 | // Create hasher 66 | if !m.Hash.Available() { 67 | return ErrHashUnavailable 68 | } 69 | hasher := m.Hash.New() 70 | hasher.Write([]byte(signingString)) 71 | 72 | // Verify the signature 73 | return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) 74 | } 75 | 76 | // Implements the Sign method from SigningMethod 77 | // For this signing method, must be an *rsa.PrivateKey structure. 78 | func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { 79 | var rsaKey *rsa.PrivateKey 80 | var ok bool 81 | 82 | // Validate type of key 83 | if rsaKey, ok = key.(*rsa.PrivateKey); !ok { 84 | return "", ErrInvalidKey 85 | } 86 | 87 | // Create the hasher 88 | if !m.Hash.Available() { 89 | return "", ErrHashUnavailable 90 | } 91 | 92 | hasher := m.Hash.New() 93 | hasher.Write([]byte(signingString)) 94 | 95 | // Sign the string and return the encoded bytes 96 | if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { 97 | return EncodeSegment(sigBytes), nil 98 | } else { 99 | return "", err 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa_pss.go: -------------------------------------------------------------------------------- 1 | // +build go1.4 2 | 3 | package jwt 4 | 5 | import ( 6 | "crypto" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | ) 10 | 11 | // Implements the RSAPSS family of signing methods signing methods 12 | type SigningMethodRSAPSS struct { 13 | *SigningMethodRSA 14 | Options *rsa.PSSOptions 15 | } 16 | 17 | // Specific instances for RS/PS and company 18 | var ( 19 | SigningMethodPS256 *SigningMethodRSAPSS 20 | SigningMethodPS384 *SigningMethodRSAPSS 21 | SigningMethodPS512 *SigningMethodRSAPSS 22 | ) 23 | 24 | func init() { 25 | // PS256 26 | SigningMethodPS256 = &SigningMethodRSAPSS{ 27 | &SigningMethodRSA{ 28 | Name: "PS256", 29 | Hash: crypto.SHA256, 30 | }, 31 | &rsa.PSSOptions{ 32 | SaltLength: rsa.PSSSaltLengthAuto, 33 | Hash: crypto.SHA256, 34 | }, 35 | } 36 | RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { 37 | return SigningMethodPS256 38 | }) 39 | 40 | // PS384 41 | SigningMethodPS384 = &SigningMethodRSAPSS{ 42 | &SigningMethodRSA{ 43 | Name: "PS384", 44 | Hash: crypto.SHA384, 45 | }, 46 | &rsa.PSSOptions{ 47 | SaltLength: rsa.PSSSaltLengthAuto, 48 | Hash: crypto.SHA384, 49 | }, 50 | } 51 | RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { 52 | return SigningMethodPS384 53 | }) 54 | 55 | // PS512 56 | SigningMethodPS512 = &SigningMethodRSAPSS{ 57 | &SigningMethodRSA{ 58 | Name: "PS512", 59 | Hash: crypto.SHA512, 60 | }, 61 | &rsa.PSSOptions{ 62 | SaltLength: rsa.PSSSaltLengthAuto, 63 | Hash: crypto.SHA512, 64 | }, 65 | } 66 | RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { 67 | return SigningMethodPS512 68 | }) 69 | } 70 | 71 | // Implements the Verify method from SigningMethod 72 | // For this verify method, key must be an rsa.PublicKey struct 73 | func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { 74 | var err error 75 | 76 | // Decode the signature 77 | var sig []byte 78 | if sig, err = DecodeSegment(signature); err != nil { 79 | return err 80 | } 81 | 82 | var rsaKey *rsa.PublicKey 83 | switch k := key.(type) { 84 | case *rsa.PublicKey: 85 | rsaKey = k 86 | default: 87 | return ErrInvalidKey 88 | } 89 | 90 | // Create hasher 91 | if !m.Hash.Available() { 92 | return ErrHashUnavailable 93 | } 94 | hasher := m.Hash.New() 95 | hasher.Write([]byte(signingString)) 96 | 97 | return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) 98 | } 99 | 100 | // Implements the Sign method from SigningMethod 101 | // For this signing method, key must be an rsa.PrivateKey struct 102 | func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { 103 | var rsaKey *rsa.PrivateKey 104 | 105 | switch k := key.(type) { 106 | case *rsa.PrivateKey: 107 | rsaKey = k 108 | default: 109 | return "", ErrInvalidKeyType 110 | } 111 | 112 | // Create the hasher 113 | if !m.Hash.Available() { 114 | return "", ErrHashUnavailable 115 | } 116 | 117 | hasher := m.Hash.New() 118 | hasher.Write([]byte(signingString)) 119 | 120 | // Sign the string and return the encoded bytes 121 | if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { 122 | return EncodeSegment(sigBytes), nil 123 | } else { 124 | return "", err 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/rsa_utils.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/x509" 6 | "encoding/pem" 7 | "errors" 8 | ) 9 | 10 | var ( 11 | ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") 12 | ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key") 13 | ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key") 14 | ) 15 | 16 | // Parse PEM encoded PKCS1 or PKCS8 private key 17 | func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { 18 | var err error 19 | 20 | // Parse PEM block 21 | var block *pem.Block 22 | if block, _ = pem.Decode(key); block == nil { 23 | return nil, ErrKeyMustBePEMEncoded 24 | } 25 | 26 | var parsedKey interface{} 27 | if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { 28 | if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { 29 | return nil, err 30 | } 31 | } 32 | 33 | var pkey *rsa.PrivateKey 34 | var ok bool 35 | if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { 36 | return nil, ErrNotRSAPrivateKey 37 | } 38 | 39 | return pkey, nil 40 | } 41 | 42 | // Parse PEM encoded PKCS1 or PKCS8 private key protected with password 43 | func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) { 44 | var err error 45 | 46 | // Parse PEM block 47 | var block *pem.Block 48 | if block, _ = pem.Decode(key); block == nil { 49 | return nil, ErrKeyMustBePEMEncoded 50 | } 51 | 52 | var parsedKey interface{} 53 | 54 | var blockDecrypted []byte 55 | if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil { 56 | return nil, err 57 | } 58 | 59 | if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil { 60 | if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil { 61 | return nil, err 62 | } 63 | } 64 | 65 | var pkey *rsa.PrivateKey 66 | var ok bool 67 | if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { 68 | return nil, ErrNotRSAPrivateKey 69 | } 70 | 71 | return pkey, nil 72 | } 73 | 74 | // Parse PEM encoded PKCS1 or PKCS8 public key 75 | func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { 76 | var err error 77 | 78 | // Parse PEM block 79 | var block *pem.Block 80 | if block, _ = pem.Decode(key); block == nil { 81 | return nil, ErrKeyMustBePEMEncoded 82 | } 83 | 84 | // Parse the key 85 | var parsedKey interface{} 86 | if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 87 | if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 88 | parsedKey = cert.PublicKey 89 | } else { 90 | return nil, err 91 | } 92 | } 93 | 94 | var pkey *rsa.PublicKey 95 | var ok bool 96 | if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { 97 | return nil, ErrNotRSAPublicKey 98 | } 99 | 100 | return pkey, nil 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/signing_method.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var signingMethods = map[string]func() SigningMethod{} 8 | var signingMethodLock = new(sync.RWMutex) 9 | 10 | // Implement SigningMethod to add new methods for signing or verifying tokens. 11 | type SigningMethod interface { 12 | Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid 13 | Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error 14 | Alg() string // returns the alg identifier for this method (example: 'HS256') 15 | } 16 | 17 | // Register the "alg" name and a factory function for signing method. 18 | // This is typically done during init() in the method's implementation 19 | func RegisterSigningMethod(alg string, f func() SigningMethod) { 20 | signingMethodLock.Lock() 21 | defer signingMethodLock.Unlock() 22 | 23 | signingMethods[alg] = f 24 | } 25 | 26 | // Get a signing method from an "alg" string 27 | func GetSigningMethod(alg string) (method SigningMethod) { 28 | signingMethodLock.RLock() 29 | defer signingMethodLock.RUnlock() 30 | 31 | if methodF, ok := signingMethods[alg]; ok { 32 | method = methodF() 33 | } 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/dgrijalva/jwt-go/token.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/json" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). 11 | // You can override it to use another time value. This is useful for testing or if your 12 | // server uses a different time zone than your tokens. 13 | var TimeFunc = time.Now 14 | 15 | // Parse methods use this callback function to supply 16 | // the key for verification. The function receives the parsed, 17 | // but unverified Token. This allows you to use properties in the 18 | // Header of the token (such as `kid`) to identify which key to use. 19 | type Keyfunc func(*Token) (interface{}, error) 20 | 21 | // A JWT Token. Different fields will be used depending on whether you're 22 | // creating or parsing/verifying a token. 23 | type Token struct { 24 | Raw string // The raw token. Populated when you Parse a token 25 | Method SigningMethod // The signing method used or to be used 26 | Header map[string]interface{} // The first segment of the token 27 | Claims Claims // The second segment of the token 28 | Signature string // The third segment of the token. Populated when you Parse a token 29 | Valid bool // Is the token valid? Populated when you Parse/Verify a token 30 | } 31 | 32 | // Create a new Token. Takes a signing method 33 | func New(method SigningMethod) *Token { 34 | return NewWithClaims(method, MapClaims{}) 35 | } 36 | 37 | func NewWithClaims(method SigningMethod, claims Claims) *Token { 38 | return &Token{ 39 | Header: map[string]interface{}{ 40 | "typ": "JWT", 41 | "alg": method.Alg(), 42 | }, 43 | Claims: claims, 44 | Method: method, 45 | } 46 | } 47 | 48 | // Get the complete, signed token 49 | func (t *Token) SignedString(key interface{}) (string, error) { 50 | var sig, sstr string 51 | var err error 52 | if sstr, err = t.SigningString(); err != nil { 53 | return "", err 54 | } 55 | if sig, err = t.Method.Sign(sstr, key); err != nil { 56 | return "", err 57 | } 58 | return strings.Join([]string{sstr, sig}, "."), nil 59 | } 60 | 61 | // Generate the signing string. This is the 62 | // most expensive part of the whole deal. Unless you 63 | // need this for something special, just go straight for 64 | // the SignedString. 65 | func (t *Token) SigningString() (string, error) { 66 | var err error 67 | parts := make([]string, 2) 68 | for i, _ := range parts { 69 | var jsonValue []byte 70 | if i == 0 { 71 | if jsonValue, err = json.Marshal(t.Header); err != nil { 72 | return "", err 73 | } 74 | } else { 75 | if jsonValue, err = json.Marshal(t.Claims); err != nil { 76 | return "", err 77 | } 78 | } 79 | 80 | parts[i] = EncodeSegment(jsonValue) 81 | } 82 | return strings.Join(parts, "."), nil 83 | } 84 | 85 | // Parse, validate, and return a token. 86 | // keyFunc will receive the parsed token and should return the key for validating. 87 | // If everything is kosher, err will be nil 88 | func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { 89 | return new(Parser).Parse(tokenString, keyFunc) 90 | } 91 | 92 | func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { 93 | return new(Parser).ParseWithClaims(tokenString, claims, keyFunc) 94 | } 95 | 96 | // Encode JWT specific base64url encoding with padding stripped 97 | func EncodeSegment(seg []byte) string { 98 | return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=") 99 | } 100 | 101 | // Decode JWT specific base64url encoding with padding stripped 102 | func DecodeSegment(seg string) ([]byte, error) { 103 | if l := len(seg) % 4; l > 0 { 104 | seg += strings.Repeat("=", 4-l) 105 | } 106 | 107 | return base64.URLEncoding.DecodeString(seg) 108 | } 109 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.7.x 7 | - go: 1.8.x 8 | - go: 1.9.x 9 | - go: 1.10.x 10 | - go: 1.11.x 11 | - go: 1.x 12 | env: LATEST=true 13 | - go: tip 14 | allow_failures: 15 | - go: tip 16 | 17 | install: 18 | - # Skip 19 | 20 | script: 21 | - go get -t -v ./... 22 | - diff -u <(echo -n) <(gofmt -d .) 23 | - if [[ "$LATEST" = true ]]; then go tool vet .; fi 24 | - go test -v -race ./... 25 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of gorilla/mux authors for copyright purposes. 2 | # 3 | # Please keep the list sorted. 4 | 5 | Google LLC (https://opensource.google.com/) 6 | Kamil Kisielk 7 | Matt Silverlock 8 | Rodrigo Moraes (https://github.com/moraes) 9 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **What version of Go are you running?** (Paste the output of `go version`) 2 | 3 | 4 | **What version of gorilla/mux are you at?** (Paste the output of `git rev-parse HEAD` inside `$GOPATH/src/github.com/gorilla/mux`) 5 | 6 | 7 | **Describe your problem** (and what you have tried so far) 8 | 9 | 10 | **Paste a minimal, runnable, reproduction of your issue below** (use backticks to format it) 11 | 12 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context.go: -------------------------------------------------------------------------------- 1 | package mux 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func contextGet(r *http.Request, key interface{}) interface{} { 9 | return r.Context().Value(key) 10 | } 11 | 12 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 13 | if val == nil { 14 | return r 15 | } 16 | 17 | return r.WithContext(context.WithValue(r.Context(), key, val)) 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gorilla/mux 2 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/middleware.go: -------------------------------------------------------------------------------- 1 | package mux 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | ) 7 | 8 | // MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler. 9 | // Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed 10 | // to it, and then calls the handler passed as parameter to the MiddlewareFunc. 11 | type MiddlewareFunc func(http.Handler) http.Handler 12 | 13 | // middleware interface is anything which implements a MiddlewareFunc named Middleware. 14 | type middleware interface { 15 | Middleware(handler http.Handler) http.Handler 16 | } 17 | 18 | // Middleware allows MiddlewareFunc to implement the middleware interface. 19 | func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler { 20 | return mw(handler) 21 | } 22 | 23 | // Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. 24 | func (r *Router) Use(mwf ...MiddlewareFunc) { 25 | for _, fn := range mwf { 26 | r.middlewares = append(r.middlewares, fn) 27 | } 28 | } 29 | 30 | // useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router. 31 | func (r *Router) useInterface(mw middleware) { 32 | r.middlewares = append(r.middlewares, mw) 33 | } 34 | 35 | // CORSMethodMiddleware sets the Access-Control-Allow-Methods response header 36 | // on a request, by matching routes based only on paths. It also handles 37 | // OPTIONS requests, by settings Access-Control-Allow-Methods, and then 38 | // returning without calling the next http handler. 39 | func CORSMethodMiddleware(r *Router) MiddlewareFunc { 40 | return func(next http.Handler) http.Handler { 41 | return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 42 | var allMethods []string 43 | 44 | err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { 45 | for _, m := range route.matchers { 46 | if _, ok := m.(*routeRegexp); ok { 47 | if m.Match(req, &RouteMatch{}) { 48 | methods, err := route.GetMethods() 49 | if err != nil { 50 | return err 51 | } 52 | 53 | allMethods = append(allMethods, methods...) 54 | } 55 | break 56 | } 57 | } 58 | return nil 59 | }) 60 | 61 | if err == nil { 62 | w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ",")) 63 | 64 | if req.Method == "OPTIONS" { 65 | return 66 | } 67 | } 68 | 69 | next.ServeHTTP(w, req) 70 | }) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/test_helpers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package mux 6 | 7 | import "net/http" 8 | 9 | // SetURLVars sets the URL variables for the given request, to be accessed via 10 | // mux.Vars for testing route behaviour. Arguments are not modified, a shallow 11 | // copy is returned. 12 | // 13 | // This API should only be used for testing purposes; it provides a way to 14 | // inject variables into the request context. Alternatively, URL variables 15 | // can be set by making a route that captures the required variables, 16 | // starting a server and sending the request to that server. 17 | func SetURLVars(r *http.Request, val map[string]string) *http.Request { 18 | return setVars(r, val) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | gofmt: 4 | enabled: true 5 | govet: 6 | enabled: true 7 | golint: 8 | enabled: true 9 | ratings: 10 | paths: 11 | - "**.go" 12 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/.gitignore: -------------------------------------------------------------------------------- 1 | documents 2 | _book 3 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-NOW Jinzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/README.md: -------------------------------------------------------------------------------- 1 | # GORM 2 | 3 | The fantastic ORM library for Golang, aims to be developer friendly. 4 | 5 | [![go report card](https://goreportcard.com/badge/github.com/jinzhu/gorm "go report card")](https://goreportcard.com/report/github.com/jinzhu/gorm) 6 | [![wercker status](https://app.wercker.com/status/8596cace912c9947dd9c8542ecc8cb8b/s/master "wercker status")](https://app.wercker.com/project/byKey/8596cace912c9947dd9c8542ecc8cb8b) 7 | [![Join the chat at https://gitter.im/jinzhu/gorm](https://img.shields.io/gitter/room/jinzhu/gorm.svg)](https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8 | [![Open Collective Backer](https://opencollective.com/gorm/tiers/backer/badge.svg?label=backer&color=brightgreen "Open Collective Backer")](https://opencollective.com/gorm) 9 | [![Open Collective Sponsor](https://opencollective.com/gorm/tiers/sponsor/badge.svg?label=sponsor&color=brightgreen "Open Collective Sponsor")](https://opencollective.com/gorm) 10 | [![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT) 11 | [![GoDoc](https://godoc.org/github.com/jinzhu/gorm?status.svg)](https://godoc.org/github.com/jinzhu/gorm) 12 | 13 | ## Overview 14 | 15 | * Full-Featured ORM (almost) 16 | * Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism) 17 | * Hooks (Before/After Create/Save/Update/Delete/Find) 18 | * Preloading (eager loading) 19 | * Transactions 20 | * Composite Primary Key 21 | * SQL Builder 22 | * Auto Migrations 23 | * Logger 24 | * Extendable, write Plugins based on GORM callbacks 25 | * Every feature comes with tests 26 | * Developer Friendly 27 | 28 | ## Getting Started 29 | 30 | * GORM Guides [http://gorm.io](http://gorm.io) 31 | 32 | ## Contributing 33 | 34 | [You can help to deliver a better GORM, check out things you can do](http://gorm.io/contribute.html) 35 | 36 | ## License 37 | 38 | © Jinzhu, 2013~time.Now 39 | 40 | Released under the [MIT License](https://github.com/jinzhu/gorm/blob/master/License) 41 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_create.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // Define callbacks for creating 9 | func init() { 10 | DefaultCallback.Create().Register("gorm:begin_transaction", beginTransactionCallback) 11 | DefaultCallback.Create().Register("gorm:before_create", beforeCreateCallback) 12 | DefaultCallback.Create().Register("gorm:save_before_associations", saveBeforeAssociationsCallback) 13 | DefaultCallback.Create().Register("gorm:update_time_stamp", updateTimeStampForCreateCallback) 14 | DefaultCallback.Create().Register("gorm:create", createCallback) 15 | DefaultCallback.Create().Register("gorm:force_reload_after_create", forceReloadAfterCreateCallback) 16 | DefaultCallback.Create().Register("gorm:save_after_associations", saveAfterAssociationsCallback) 17 | DefaultCallback.Create().Register("gorm:after_create", afterCreateCallback) 18 | DefaultCallback.Create().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) 19 | } 20 | 21 | // beforeCreateCallback will invoke `BeforeSave`, `BeforeCreate` method before creating 22 | func beforeCreateCallback(scope *Scope) { 23 | if !scope.HasError() { 24 | scope.CallMethod("BeforeSave") 25 | } 26 | if !scope.HasError() { 27 | scope.CallMethod("BeforeCreate") 28 | } 29 | } 30 | 31 | // updateTimeStampForCreateCallback will set `CreatedAt`, `UpdatedAt` when creating 32 | func updateTimeStampForCreateCallback(scope *Scope) { 33 | if !scope.HasError() { 34 | now := NowFunc() 35 | 36 | if createdAtField, ok := scope.FieldByName("CreatedAt"); ok { 37 | if createdAtField.IsBlank { 38 | createdAtField.Set(now) 39 | } 40 | } 41 | 42 | if updatedAtField, ok := scope.FieldByName("UpdatedAt"); ok { 43 | if updatedAtField.IsBlank { 44 | updatedAtField.Set(now) 45 | } 46 | } 47 | } 48 | } 49 | 50 | // createCallback the callback used to insert data into database 51 | func createCallback(scope *Scope) { 52 | if !scope.HasError() { 53 | defer scope.trace(NowFunc()) 54 | 55 | var ( 56 | columns, placeholders []string 57 | blankColumnsWithDefaultValue []string 58 | ) 59 | 60 | for _, field := range scope.Fields() { 61 | if scope.changeableField(field) { 62 | if field.IsNormal && !field.IsIgnored { 63 | if field.IsBlank && field.HasDefaultValue { 64 | blankColumnsWithDefaultValue = append(blankColumnsWithDefaultValue, scope.Quote(field.DBName)) 65 | scope.InstanceSet("gorm:blank_columns_with_default_value", blankColumnsWithDefaultValue) 66 | } else if !field.IsPrimaryKey || !field.IsBlank { 67 | columns = append(columns, scope.Quote(field.DBName)) 68 | placeholders = append(placeholders, scope.AddToVars(field.Field.Interface())) 69 | } 70 | } else if field.Relationship != nil && field.Relationship.Kind == "belongs_to" { 71 | for _, foreignKey := range field.Relationship.ForeignDBNames { 72 | if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { 73 | columns = append(columns, scope.Quote(foreignField.DBName)) 74 | placeholders = append(placeholders, scope.AddToVars(foreignField.Field.Interface())) 75 | } 76 | } 77 | } 78 | } 79 | } 80 | 81 | var ( 82 | returningColumn = "*" 83 | quotedTableName = scope.QuotedTableName() 84 | primaryField = scope.PrimaryField() 85 | extraOption string 86 | ) 87 | 88 | if str, ok := scope.Get("gorm:insert_option"); ok { 89 | extraOption = fmt.Sprint(str) 90 | } 91 | 92 | if primaryField != nil { 93 | returningColumn = scope.Quote(primaryField.DBName) 94 | } 95 | 96 | lastInsertIDReturningSuffix := scope.Dialect().LastInsertIDReturningSuffix(quotedTableName, returningColumn) 97 | 98 | if len(columns) == 0 { 99 | scope.Raw(fmt.Sprintf( 100 | "INSERT INTO %v %v%v%v", 101 | quotedTableName, 102 | scope.Dialect().DefaultValueStr(), 103 | addExtraSpaceIfExist(extraOption), 104 | addExtraSpaceIfExist(lastInsertIDReturningSuffix), 105 | )) 106 | } else { 107 | scope.Raw(fmt.Sprintf( 108 | "INSERT INTO %v (%v) VALUES (%v)%v%v", 109 | scope.QuotedTableName(), 110 | strings.Join(columns, ","), 111 | strings.Join(placeholders, ","), 112 | addExtraSpaceIfExist(extraOption), 113 | addExtraSpaceIfExist(lastInsertIDReturningSuffix), 114 | )) 115 | } 116 | 117 | // execute create sql 118 | if lastInsertIDReturningSuffix == "" || primaryField == nil { 119 | if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil { 120 | // set rows affected count 121 | scope.db.RowsAffected, _ = result.RowsAffected() 122 | 123 | // set primary value to primary field 124 | if primaryField != nil && primaryField.IsBlank { 125 | if primaryValue, err := result.LastInsertId(); scope.Err(err) == nil { 126 | scope.Err(primaryField.Set(primaryValue)) 127 | } 128 | } 129 | } 130 | } else { 131 | if primaryField.Field.CanAddr() { 132 | if err := scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...).Scan(primaryField.Field.Addr().Interface()); scope.Err(err) == nil { 133 | primaryField.IsBlank = false 134 | scope.db.RowsAffected = 1 135 | } 136 | } else { 137 | scope.Err(ErrUnaddressable) 138 | } 139 | } 140 | } 141 | } 142 | 143 | // forceReloadAfterCreateCallback will reload columns that having default value, and set it back to current object 144 | func forceReloadAfterCreateCallback(scope *Scope) { 145 | if blankColumnsWithDefaultValue, ok := scope.InstanceGet("gorm:blank_columns_with_default_value"); ok { 146 | db := scope.DB().New().Table(scope.TableName()).Select(blankColumnsWithDefaultValue.([]string)) 147 | for _, field := range scope.Fields() { 148 | if field.IsPrimaryKey && !field.IsBlank { 149 | db = db.Where(fmt.Sprintf("%v = ?", field.DBName), field.Field.Interface()) 150 | } 151 | } 152 | db.Scan(scope.Value) 153 | } 154 | } 155 | 156 | // afterCreateCallback will invoke `AfterCreate`, `AfterSave` method after creating 157 | func afterCreateCallback(scope *Scope) { 158 | if !scope.HasError() { 159 | scope.CallMethod("AfterCreate") 160 | } 161 | if !scope.HasError() { 162 | scope.CallMethod("AfterSave") 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_delete.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // Define callbacks for deleting 9 | func init() { 10 | DefaultCallback.Delete().Register("gorm:begin_transaction", beginTransactionCallback) 11 | DefaultCallback.Delete().Register("gorm:before_delete", beforeDeleteCallback) 12 | DefaultCallback.Delete().Register("gorm:delete", deleteCallback) 13 | DefaultCallback.Delete().Register("gorm:after_delete", afterDeleteCallback) 14 | DefaultCallback.Delete().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) 15 | } 16 | 17 | // beforeDeleteCallback will invoke `BeforeDelete` method before deleting 18 | func beforeDeleteCallback(scope *Scope) { 19 | if scope.DB().HasBlockGlobalUpdate() && !scope.hasConditions() { 20 | scope.Err(errors.New("Missing WHERE clause while deleting")) 21 | return 22 | } 23 | if !scope.HasError() { 24 | scope.CallMethod("BeforeDelete") 25 | } 26 | } 27 | 28 | // deleteCallback used to delete data from database or set deleted_at to current time (when using with soft delete) 29 | func deleteCallback(scope *Scope) { 30 | if !scope.HasError() { 31 | var extraOption string 32 | if str, ok := scope.Get("gorm:delete_option"); ok { 33 | extraOption = fmt.Sprint(str) 34 | } 35 | 36 | deletedAtField, hasDeletedAtField := scope.FieldByName("DeletedAt") 37 | 38 | if !scope.Search.Unscoped && hasDeletedAtField { 39 | scope.Raw(fmt.Sprintf( 40 | "UPDATE %v SET %v=%v%v%v", 41 | scope.QuotedTableName(), 42 | scope.Quote(deletedAtField.DBName), 43 | scope.AddToVars(NowFunc()), 44 | addExtraSpaceIfExist(scope.CombinedConditionSql()), 45 | addExtraSpaceIfExist(extraOption), 46 | )).Exec() 47 | } else { 48 | scope.Raw(fmt.Sprintf( 49 | "DELETE FROM %v%v%v", 50 | scope.QuotedTableName(), 51 | addExtraSpaceIfExist(scope.CombinedConditionSql()), 52 | addExtraSpaceIfExist(extraOption), 53 | )).Exec() 54 | } 55 | } 56 | } 57 | 58 | // afterDeleteCallback will invoke `AfterDelete` method after deleting 59 | func afterDeleteCallback(scope *Scope) { 60 | if !scope.HasError() { 61 | scope.CallMethod("AfterDelete") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_query.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | // Define callbacks for querying 10 | func init() { 11 | DefaultCallback.Query().Register("gorm:query", queryCallback) 12 | DefaultCallback.Query().Register("gorm:preload", preloadCallback) 13 | DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback) 14 | } 15 | 16 | // queryCallback used to query data from database 17 | func queryCallback(scope *Scope) { 18 | if _, skip := scope.InstanceGet("gorm:skip_query_callback"); skip { 19 | return 20 | } 21 | 22 | //we are only preloading relations, dont touch base model 23 | if _, skip := scope.InstanceGet("gorm:only_preload"); skip { 24 | return 25 | } 26 | 27 | defer scope.trace(NowFunc()) 28 | 29 | var ( 30 | isSlice, isPtr bool 31 | resultType reflect.Type 32 | results = scope.IndirectValue() 33 | ) 34 | 35 | if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok { 36 | if primaryField := scope.PrimaryField(); primaryField != nil { 37 | scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy)) 38 | } 39 | } 40 | 41 | if value, ok := scope.Get("gorm:query_destination"); ok { 42 | results = indirect(reflect.ValueOf(value)) 43 | } 44 | 45 | if kind := results.Kind(); kind == reflect.Slice { 46 | isSlice = true 47 | resultType = results.Type().Elem() 48 | results.Set(reflect.MakeSlice(results.Type(), 0, 0)) 49 | 50 | if resultType.Kind() == reflect.Ptr { 51 | isPtr = true 52 | resultType = resultType.Elem() 53 | } 54 | } else if kind != reflect.Struct { 55 | scope.Err(errors.New("unsupported destination, should be slice or struct")) 56 | return 57 | } 58 | 59 | scope.prepareQuerySQL() 60 | 61 | if !scope.HasError() { 62 | scope.db.RowsAffected = 0 63 | if str, ok := scope.Get("gorm:query_option"); ok { 64 | scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str)) 65 | } 66 | 67 | if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil { 68 | defer rows.Close() 69 | 70 | columns, _ := rows.Columns() 71 | for rows.Next() { 72 | scope.db.RowsAffected++ 73 | 74 | elem := results 75 | if isSlice { 76 | elem = reflect.New(resultType).Elem() 77 | } 78 | 79 | scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields()) 80 | 81 | if isSlice { 82 | if isPtr { 83 | results.Set(reflect.Append(results, elem.Addr())) 84 | } else { 85 | results.Set(reflect.Append(results, elem)) 86 | } 87 | } 88 | } 89 | 90 | if err := rows.Err(); err != nil { 91 | scope.Err(err) 92 | } else if scope.db.RowsAffected == 0 && !isSlice { 93 | scope.Err(ErrRecordNotFound) 94 | } 95 | } 96 | } 97 | } 98 | 99 | // afterQueryCallback will invoke `AfterFind` method after querying 100 | func afterQueryCallback(scope *Scope) { 101 | if !scope.HasError() { 102 | scope.CallMethod("AfterFind") 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_row_query.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import "database/sql" 4 | 5 | // Define callbacks for row query 6 | func init() { 7 | DefaultCallback.RowQuery().Register("gorm:row_query", rowQueryCallback) 8 | } 9 | 10 | type RowQueryResult struct { 11 | Row *sql.Row 12 | } 13 | 14 | type RowsQueryResult struct { 15 | Rows *sql.Rows 16 | Error error 17 | } 18 | 19 | // queryCallback used to query data from database 20 | func rowQueryCallback(scope *Scope) { 21 | if result, ok := scope.InstanceGet("row_query_result"); ok { 22 | scope.prepareQuerySQL() 23 | 24 | if rowResult, ok := result.(*RowQueryResult); ok { 25 | rowResult.Row = scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...) 26 | } else if rowsResult, ok := result.(*RowsQueryResult); ok { 27 | rowsResult.Rows, rowsResult.Error = scope.SQLDB().Query(scope.SQL, scope.SQLVars...) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_save.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | func beginTransactionCallback(scope *Scope) { 9 | scope.Begin() 10 | } 11 | 12 | func commitOrRollbackTransactionCallback(scope *Scope) { 13 | scope.CommitOrRollback() 14 | } 15 | 16 | func saveAssociationCheck(scope *Scope, field *Field) (autoUpdate bool, autoCreate bool, saveReference bool, r *Relationship) { 17 | checkTruth := func(value interface{}) bool { 18 | if v, ok := value.(bool); ok && !v { 19 | return false 20 | } 21 | 22 | if v, ok := value.(string); ok { 23 | v = strings.ToLower(v) 24 | return v == "true" 25 | } 26 | 27 | return true 28 | } 29 | 30 | if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { 31 | if r = field.Relationship; r != nil { 32 | autoUpdate, autoCreate, saveReference = true, true, true 33 | 34 | if value, ok := scope.Get("gorm:save_associations"); ok { 35 | autoUpdate = checkTruth(value) 36 | autoCreate = autoUpdate 37 | saveReference = autoUpdate 38 | } else if value, ok := field.TagSettingsGet("SAVE_ASSOCIATIONS"); ok { 39 | autoUpdate = checkTruth(value) 40 | autoCreate = autoUpdate 41 | saveReference = autoUpdate 42 | } 43 | 44 | if value, ok := scope.Get("gorm:association_autoupdate"); ok { 45 | autoUpdate = checkTruth(value) 46 | } else if value, ok := field.TagSettingsGet("ASSOCIATION_AUTOUPDATE"); ok { 47 | autoUpdate = checkTruth(value) 48 | } 49 | 50 | if value, ok := scope.Get("gorm:association_autocreate"); ok { 51 | autoCreate = checkTruth(value) 52 | } else if value, ok := field.TagSettingsGet("ASSOCIATION_AUTOCREATE"); ok { 53 | autoCreate = checkTruth(value) 54 | } 55 | 56 | if value, ok := scope.Get("gorm:association_save_reference"); ok { 57 | saveReference = checkTruth(value) 58 | } else if value, ok := field.TagSettingsGet("ASSOCIATION_SAVE_REFERENCE"); ok { 59 | saveReference = checkTruth(value) 60 | } 61 | } 62 | } 63 | 64 | return 65 | } 66 | 67 | func saveBeforeAssociationsCallback(scope *Scope) { 68 | for _, field := range scope.Fields() { 69 | autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field) 70 | 71 | if relationship != nil && relationship.Kind == "belongs_to" { 72 | fieldValue := field.Field.Addr().Interface() 73 | newScope := scope.New(fieldValue) 74 | 75 | if newScope.PrimaryKeyZero() { 76 | if autoCreate { 77 | scope.Err(scope.NewDB().Save(fieldValue).Error) 78 | } 79 | } else if autoUpdate { 80 | scope.Err(scope.NewDB().Save(fieldValue).Error) 81 | } 82 | 83 | if saveReference { 84 | if len(relationship.ForeignFieldNames) != 0 { 85 | // set value's foreign key 86 | for idx, fieldName := range relationship.ForeignFieldNames { 87 | associationForeignName := relationship.AssociationForeignDBNames[idx] 88 | if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { 89 | scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | func saveAfterAssociationsCallback(scope *Scope) { 99 | for _, field := range scope.Fields() { 100 | autoUpdate, autoCreate, saveReference, relationship := saveAssociationCheck(scope, field) 101 | 102 | if relationship != nil && (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") { 103 | value := field.Field 104 | 105 | switch value.Kind() { 106 | case reflect.Slice: 107 | for i := 0; i < value.Len(); i++ { 108 | newDB := scope.NewDB() 109 | elem := value.Index(i).Addr().Interface() 110 | newScope := newDB.NewScope(elem) 111 | 112 | if saveReference { 113 | if relationship.JoinTableHandler == nil && len(relationship.ForeignFieldNames) != 0 { 114 | for idx, fieldName := range relationship.ForeignFieldNames { 115 | associationForeignName := relationship.AssociationForeignDBNames[idx] 116 | if f, ok := scope.FieldByName(associationForeignName); ok { 117 | scope.Err(newScope.SetColumn(fieldName, f.Field.Interface())) 118 | } 119 | } 120 | } 121 | 122 | if relationship.PolymorphicType != "" { 123 | scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue)) 124 | } 125 | } 126 | 127 | if newScope.PrimaryKeyZero() { 128 | if autoCreate { 129 | scope.Err(newDB.Save(elem).Error) 130 | } 131 | } else if autoUpdate { 132 | scope.Err(newDB.Save(elem).Error) 133 | } 134 | 135 | if !scope.New(newScope.Value).PrimaryKeyZero() && saveReference { 136 | if joinTableHandler := relationship.JoinTableHandler; joinTableHandler != nil { 137 | scope.Err(joinTableHandler.Add(joinTableHandler, newDB, scope.Value, newScope.Value)) 138 | } 139 | } 140 | } 141 | default: 142 | elem := value.Addr().Interface() 143 | newScope := scope.New(elem) 144 | 145 | if saveReference { 146 | if len(relationship.ForeignFieldNames) != 0 { 147 | for idx, fieldName := range relationship.ForeignFieldNames { 148 | associationForeignName := relationship.AssociationForeignDBNames[idx] 149 | if f, ok := scope.FieldByName(associationForeignName); ok { 150 | scope.Err(newScope.SetColumn(fieldName, f.Field.Interface())) 151 | } 152 | } 153 | } 154 | 155 | if relationship.PolymorphicType != "" { 156 | scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue)) 157 | } 158 | } 159 | 160 | if newScope.PrimaryKeyZero() { 161 | if autoCreate { 162 | scope.Err(scope.NewDB().Save(elem).Error) 163 | } 164 | } else if autoUpdate { 165 | scope.Err(scope.NewDB().Save(elem).Error) 166 | } 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/callback_update.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sort" 7 | "strings" 8 | ) 9 | 10 | // Define callbacks for updating 11 | func init() { 12 | DefaultCallback.Update().Register("gorm:assign_updating_attributes", assignUpdatingAttributesCallback) 13 | DefaultCallback.Update().Register("gorm:begin_transaction", beginTransactionCallback) 14 | DefaultCallback.Update().Register("gorm:before_update", beforeUpdateCallback) 15 | DefaultCallback.Update().Register("gorm:save_before_associations", saveBeforeAssociationsCallback) 16 | DefaultCallback.Update().Register("gorm:update_time_stamp", updateTimeStampForUpdateCallback) 17 | DefaultCallback.Update().Register("gorm:update", updateCallback) 18 | DefaultCallback.Update().Register("gorm:save_after_associations", saveAfterAssociationsCallback) 19 | DefaultCallback.Update().Register("gorm:after_update", afterUpdateCallback) 20 | DefaultCallback.Update().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) 21 | } 22 | 23 | // assignUpdatingAttributesCallback assign updating attributes to model 24 | func assignUpdatingAttributesCallback(scope *Scope) { 25 | if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok { 26 | if updateMaps, hasUpdate := scope.updatedAttrsWithValues(attrs); hasUpdate { 27 | scope.InstanceSet("gorm:update_attrs", updateMaps) 28 | } else { 29 | scope.SkipLeft() 30 | } 31 | } 32 | } 33 | 34 | // beforeUpdateCallback will invoke `BeforeSave`, `BeforeUpdate` method before updating 35 | func beforeUpdateCallback(scope *Scope) { 36 | if scope.DB().HasBlockGlobalUpdate() && !scope.hasConditions() { 37 | scope.Err(errors.New("Missing WHERE clause while updating")) 38 | return 39 | } 40 | if _, ok := scope.Get("gorm:update_column"); !ok { 41 | if !scope.HasError() { 42 | scope.CallMethod("BeforeSave") 43 | } 44 | if !scope.HasError() { 45 | scope.CallMethod("BeforeUpdate") 46 | } 47 | } 48 | } 49 | 50 | // updateTimeStampForUpdateCallback will set `UpdatedAt` when updating 51 | func updateTimeStampForUpdateCallback(scope *Scope) { 52 | if _, ok := scope.Get("gorm:update_column"); !ok { 53 | scope.SetColumn("UpdatedAt", NowFunc()) 54 | } 55 | } 56 | 57 | // updateCallback the callback used to update data to database 58 | func updateCallback(scope *Scope) { 59 | if !scope.HasError() { 60 | var sqls []string 61 | 62 | if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok { 63 | // Sort the column names so that the generated SQL is the same every time. 64 | updateMap := updateAttrs.(map[string]interface{}) 65 | var columns []string 66 | for c := range updateMap { 67 | columns = append(columns, c) 68 | } 69 | sort.Strings(columns) 70 | 71 | for _, column := range columns { 72 | value := updateMap[column] 73 | sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(column), scope.AddToVars(value))) 74 | } 75 | } else { 76 | for _, field := range scope.Fields() { 77 | if scope.changeableField(field) { 78 | if !field.IsPrimaryKey && field.IsNormal { 79 | if !field.IsForeignKey || !field.IsBlank || !field.HasDefaultValue { 80 | sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) 81 | } 82 | } else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { 83 | for _, foreignKey := range relationship.ForeignDBNames { 84 | if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { 85 | sqls = append(sqls, 86 | fmt.Sprintf("%v = %v", scope.Quote(foreignField.DBName), scope.AddToVars(foreignField.Field.Interface()))) 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | var extraOption string 95 | if str, ok := scope.Get("gorm:update_option"); ok { 96 | extraOption = fmt.Sprint(str) 97 | } 98 | 99 | if len(sqls) > 0 { 100 | scope.Raw(fmt.Sprintf( 101 | "UPDATE %v SET %v%v%v", 102 | scope.QuotedTableName(), 103 | strings.Join(sqls, ", "), 104 | addExtraSpaceIfExist(scope.CombinedConditionSql()), 105 | addExtraSpaceIfExist(extraOption), 106 | )).Exec() 107 | } 108 | } 109 | } 110 | 111 | // afterUpdateCallback will invoke `AfterUpdate`, `AfterSave` method after updating 112 | func afterUpdateCallback(scope *Scope) { 113 | if _, ok := scope.Get("gorm:update_column"); !ok { 114 | if !scope.HasError() { 115 | scope.CallMethod("AfterUpdate") 116 | } 117 | if !scope.HasError() { 118 | scope.CallMethod("AfterSave") 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialect.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "reflect" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Dialect interface contains behaviors that differ across SQL database 12 | type Dialect interface { 13 | // GetName get dialect's name 14 | GetName() string 15 | 16 | // SetDB set db for dialect 17 | SetDB(db SQLCommon) 18 | 19 | // BindVar return the placeholder for actual values in SQL statements, in many dbs it is "?", Postgres using $1 20 | BindVar(i int) string 21 | // Quote quotes field name to avoid SQL parsing exceptions by using a reserved word as a field name 22 | Quote(key string) string 23 | // DataTypeOf return data's sql type 24 | DataTypeOf(field *StructField) string 25 | 26 | // HasIndex check has index or not 27 | HasIndex(tableName string, indexName string) bool 28 | // HasForeignKey check has foreign key or not 29 | HasForeignKey(tableName string, foreignKeyName string) bool 30 | // RemoveIndex remove index 31 | RemoveIndex(tableName string, indexName string) error 32 | // HasTable check has table or not 33 | HasTable(tableName string) bool 34 | // HasColumn check has column or not 35 | HasColumn(tableName string, columnName string) bool 36 | // ModifyColumn modify column's type 37 | ModifyColumn(tableName string, columnName string, typ string) error 38 | 39 | // LimitAndOffsetSQL return generated SQL with Limit and Offset, as mssql has special case 40 | LimitAndOffsetSQL(limit, offset interface{}) string 41 | // SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL` 42 | SelectFromDummyTable() string 43 | // LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING` 44 | LastInsertIDReturningSuffix(tableName, columnName string) string 45 | // DefaultValueStr 46 | DefaultValueStr() string 47 | 48 | // BuildKeyName returns a valid key name (foreign key, index key) for the given table, field and reference 49 | BuildKeyName(kind, tableName string, fields ...string) string 50 | 51 | // CurrentDatabase return current database name 52 | CurrentDatabase() string 53 | } 54 | 55 | var dialectsMap = map[string]Dialect{} 56 | 57 | func newDialect(name string, db SQLCommon) Dialect { 58 | if value, ok := dialectsMap[name]; ok { 59 | dialect := reflect.New(reflect.TypeOf(value).Elem()).Interface().(Dialect) 60 | dialect.SetDB(db) 61 | return dialect 62 | } 63 | 64 | fmt.Printf("`%v` is not officially supported, running under compatibility mode.\n", name) 65 | commontDialect := &commonDialect{} 66 | commontDialect.SetDB(db) 67 | return commontDialect 68 | } 69 | 70 | // RegisterDialect register new dialect 71 | func RegisterDialect(name string, dialect Dialect) { 72 | dialectsMap[name] = dialect 73 | } 74 | 75 | // GetDialect gets the dialect for the specified dialect name 76 | func GetDialect(name string) (dialect Dialect, ok bool) { 77 | dialect, ok = dialectsMap[name] 78 | return 79 | } 80 | 81 | // ParseFieldStructForDialect get field's sql data type 82 | var ParseFieldStructForDialect = func(field *StructField, dialect Dialect) (fieldValue reflect.Value, sqlType string, size int, additionalType string) { 83 | // Get redirected field type 84 | var ( 85 | reflectType = field.Struct.Type 86 | dataType, _ = field.TagSettingsGet("TYPE") 87 | ) 88 | 89 | for reflectType.Kind() == reflect.Ptr { 90 | reflectType = reflectType.Elem() 91 | } 92 | 93 | // Get redirected field value 94 | fieldValue = reflect.Indirect(reflect.New(reflectType)) 95 | 96 | if gormDataType, ok := fieldValue.Interface().(interface { 97 | GormDataType(Dialect) string 98 | }); ok { 99 | dataType = gormDataType.GormDataType(dialect) 100 | } 101 | 102 | // Get scanner's real value 103 | if dataType == "" { 104 | var getScannerValue func(reflect.Value) 105 | getScannerValue = func(value reflect.Value) { 106 | fieldValue = value 107 | if _, isScanner := reflect.New(fieldValue.Type()).Interface().(sql.Scanner); isScanner && fieldValue.Kind() == reflect.Struct { 108 | getScannerValue(fieldValue.Field(0)) 109 | } 110 | } 111 | getScannerValue(fieldValue) 112 | } 113 | 114 | // Default Size 115 | if num, ok := field.TagSettingsGet("SIZE"); ok { 116 | size, _ = strconv.Atoi(num) 117 | } else { 118 | size = 255 119 | } 120 | 121 | // Default type from tag setting 122 | notNull, _ := field.TagSettingsGet("NOT NULL") 123 | unique, _ := field.TagSettingsGet("UNIQUE") 124 | additionalType = notNull + " " + unique 125 | if value, ok := field.TagSettingsGet("DEFAULT"); ok { 126 | additionalType = additionalType + " DEFAULT " + value 127 | } 128 | 129 | return fieldValue, dataType, size, strings.TrimSpace(additionalType) 130 | } 131 | 132 | func currentDatabaseAndTable(dialect Dialect, tableName string) (string, string) { 133 | if strings.Contains(tableName, ".") { 134 | splitStrings := strings.SplitN(tableName, ".", 2) 135 | return splitStrings[0], splitStrings[1] 136 | } 137 | return dialect.CurrentDatabase(), tableName 138 | } 139 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialect_common.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // DefaultForeignKeyNamer contains the default foreign key name generator method 13 | type DefaultForeignKeyNamer struct { 14 | } 15 | 16 | type commonDialect struct { 17 | db SQLCommon 18 | DefaultForeignKeyNamer 19 | } 20 | 21 | func init() { 22 | RegisterDialect("common", &commonDialect{}) 23 | } 24 | 25 | func (commonDialect) GetName() string { 26 | return "common" 27 | } 28 | 29 | func (s *commonDialect) SetDB(db SQLCommon) { 30 | s.db = db 31 | } 32 | 33 | func (commonDialect) BindVar(i int) string { 34 | return "$$$" // ? 35 | } 36 | 37 | func (commonDialect) Quote(key string) string { 38 | return fmt.Sprintf(`"%s"`, key) 39 | } 40 | 41 | func (s *commonDialect) fieldCanAutoIncrement(field *StructField) bool { 42 | if value, ok := field.TagSettingsGet("AUTO_INCREMENT"); ok { 43 | return strings.ToLower(value) != "false" 44 | } 45 | return field.IsPrimaryKey 46 | } 47 | 48 | func (s *commonDialect) DataTypeOf(field *StructField) string { 49 | var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) 50 | 51 | if sqlType == "" { 52 | switch dataValue.Kind() { 53 | case reflect.Bool: 54 | sqlType = "BOOLEAN" 55 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: 56 | if s.fieldCanAutoIncrement(field) { 57 | sqlType = "INTEGER AUTO_INCREMENT" 58 | } else { 59 | sqlType = "INTEGER" 60 | } 61 | case reflect.Int64, reflect.Uint64: 62 | if s.fieldCanAutoIncrement(field) { 63 | sqlType = "BIGINT AUTO_INCREMENT" 64 | } else { 65 | sqlType = "BIGINT" 66 | } 67 | case reflect.Float32, reflect.Float64: 68 | sqlType = "FLOAT" 69 | case reflect.String: 70 | if size > 0 && size < 65532 { 71 | sqlType = fmt.Sprintf("VARCHAR(%d)", size) 72 | } else { 73 | sqlType = "VARCHAR(65532)" 74 | } 75 | case reflect.Struct: 76 | if _, ok := dataValue.Interface().(time.Time); ok { 77 | sqlType = "TIMESTAMP" 78 | } 79 | default: 80 | if _, ok := dataValue.Interface().([]byte); ok { 81 | if size > 0 && size < 65532 { 82 | sqlType = fmt.Sprintf("BINARY(%d)", size) 83 | } else { 84 | sqlType = "BINARY(65532)" 85 | } 86 | } 87 | } 88 | } 89 | 90 | if sqlType == "" { 91 | panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", dataValue.Type().Name(), dataValue.Kind().String())) 92 | } 93 | 94 | if strings.TrimSpace(additionalType) == "" { 95 | return sqlType 96 | } 97 | return fmt.Sprintf("%v %v", sqlType, additionalType) 98 | } 99 | 100 | func (s commonDialect) HasIndex(tableName string, indexName string) bool { 101 | var count int 102 | currentDatabase, tableName := currentDatabaseAndTable(&s, tableName) 103 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = ? AND table_name = ? AND index_name = ?", currentDatabase, tableName, indexName).Scan(&count) 104 | return count > 0 105 | } 106 | 107 | func (s commonDialect) RemoveIndex(tableName string, indexName string) error { 108 | _, err := s.db.Exec(fmt.Sprintf("DROP INDEX %v", indexName)) 109 | return err 110 | } 111 | 112 | func (s commonDialect) HasForeignKey(tableName string, foreignKeyName string) bool { 113 | return false 114 | } 115 | 116 | func (s commonDialect) HasTable(tableName string) bool { 117 | var count int 118 | currentDatabase, tableName := currentDatabaseAndTable(&s, tableName) 119 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = ? AND table_name = ?", currentDatabase, tableName).Scan(&count) 120 | return count > 0 121 | } 122 | 123 | func (s commonDialect) HasColumn(tableName string, columnName string) bool { 124 | var count int 125 | currentDatabase, tableName := currentDatabaseAndTable(&s, tableName) 126 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = ? AND table_name = ? AND column_name = ?", currentDatabase, tableName, columnName).Scan(&count) 127 | return count > 0 128 | } 129 | 130 | func (s commonDialect) ModifyColumn(tableName string, columnName string, typ string) error { 131 | _, err := s.db.Exec(fmt.Sprintf("ALTER TABLE %v ALTER COLUMN %v TYPE %v", tableName, columnName, typ)) 132 | return err 133 | } 134 | 135 | func (s commonDialect) CurrentDatabase() (name string) { 136 | s.db.QueryRow("SELECT DATABASE()").Scan(&name) 137 | return 138 | } 139 | 140 | func (commonDialect) LimitAndOffsetSQL(limit, offset interface{}) (sql string) { 141 | if limit != nil { 142 | if parsedLimit, err := strconv.ParseInt(fmt.Sprint(limit), 0, 0); err == nil && parsedLimit >= 0 { 143 | sql += fmt.Sprintf(" LIMIT %d", parsedLimit) 144 | } 145 | } 146 | if offset != nil { 147 | if parsedOffset, err := strconv.ParseInt(fmt.Sprint(offset), 0, 0); err == nil && parsedOffset >= 0 { 148 | sql += fmt.Sprintf(" OFFSET %d", parsedOffset) 149 | } 150 | } 151 | return 152 | } 153 | 154 | func (commonDialect) SelectFromDummyTable() string { 155 | return "" 156 | } 157 | 158 | func (commonDialect) LastInsertIDReturningSuffix(tableName, columnName string) string { 159 | return "" 160 | } 161 | 162 | func (commonDialect) DefaultValueStr() string { 163 | return "DEFAULT VALUES" 164 | } 165 | 166 | // BuildKeyName returns a valid key name (foreign key, index key) for the given table, field and reference 167 | func (DefaultForeignKeyNamer) BuildKeyName(kind, tableName string, fields ...string) string { 168 | keyName := fmt.Sprintf("%s_%s_%s", kind, tableName, strings.Join(fields, "_")) 169 | keyName = regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString(keyName, "_") 170 | return keyName 171 | } 172 | 173 | // IsByteArrayOrSlice returns true of the reflected value is an array or slice 174 | func IsByteArrayOrSlice(value reflect.Value) bool { 175 | return (value.Kind() == reflect.Array || value.Kind() == reflect.Slice) && value.Type().Elem() == reflect.TypeOf(uint8(0)) 176 | } 177 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialect_mysql.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "crypto/sha1" 5 | "fmt" 6 | "reflect" 7 | "regexp" 8 | "strconv" 9 | "strings" 10 | "time" 11 | "unicode/utf8" 12 | ) 13 | 14 | type mysql struct { 15 | commonDialect 16 | } 17 | 18 | func init() { 19 | RegisterDialect("mysql", &mysql{}) 20 | } 21 | 22 | func (mysql) GetName() string { 23 | return "mysql" 24 | } 25 | 26 | func (mysql) Quote(key string) string { 27 | return fmt.Sprintf("`%s`", key) 28 | } 29 | 30 | // Get Data Type for MySQL Dialect 31 | func (s *mysql) DataTypeOf(field *StructField) string { 32 | var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) 33 | 34 | // MySQL allows only one auto increment column per table, and it must 35 | // be a KEY column. 36 | if _, ok := field.TagSettingsGet("AUTO_INCREMENT"); ok { 37 | if _, ok = field.TagSettingsGet("INDEX"); !ok && !field.IsPrimaryKey { 38 | field.TagSettingsDelete("AUTO_INCREMENT") 39 | } 40 | } 41 | 42 | if sqlType == "" { 43 | switch dataValue.Kind() { 44 | case reflect.Bool: 45 | sqlType = "boolean" 46 | case reflect.Int8: 47 | if s.fieldCanAutoIncrement(field) { 48 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 49 | sqlType = "tinyint AUTO_INCREMENT" 50 | } else { 51 | sqlType = "tinyint" 52 | } 53 | case reflect.Int, reflect.Int16, reflect.Int32: 54 | if s.fieldCanAutoIncrement(field) { 55 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 56 | sqlType = "int AUTO_INCREMENT" 57 | } else { 58 | sqlType = "int" 59 | } 60 | case reflect.Uint8: 61 | if s.fieldCanAutoIncrement(field) { 62 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 63 | sqlType = "tinyint unsigned AUTO_INCREMENT" 64 | } else { 65 | sqlType = "tinyint unsigned" 66 | } 67 | case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uintptr: 68 | if s.fieldCanAutoIncrement(field) { 69 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 70 | sqlType = "int unsigned AUTO_INCREMENT" 71 | } else { 72 | sqlType = "int unsigned" 73 | } 74 | case reflect.Int64: 75 | if s.fieldCanAutoIncrement(field) { 76 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 77 | sqlType = "bigint AUTO_INCREMENT" 78 | } else { 79 | sqlType = "bigint" 80 | } 81 | case reflect.Uint64: 82 | if s.fieldCanAutoIncrement(field) { 83 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 84 | sqlType = "bigint unsigned AUTO_INCREMENT" 85 | } else { 86 | sqlType = "bigint unsigned" 87 | } 88 | case reflect.Float32, reflect.Float64: 89 | sqlType = "double" 90 | case reflect.String: 91 | if size > 0 && size < 65532 { 92 | sqlType = fmt.Sprintf("varchar(%d)", size) 93 | } else { 94 | sqlType = "longtext" 95 | } 96 | case reflect.Struct: 97 | if _, ok := dataValue.Interface().(time.Time); ok { 98 | precision := "" 99 | if p, ok := field.TagSettingsGet("PRECISION"); ok { 100 | precision = fmt.Sprintf("(%s)", p) 101 | } 102 | 103 | if _, ok := field.TagSettingsGet("NOT NULL"); ok { 104 | sqlType = fmt.Sprintf("timestamp%v", precision) 105 | } else { 106 | sqlType = fmt.Sprintf("timestamp%v NULL", precision) 107 | } 108 | } 109 | default: 110 | if IsByteArrayOrSlice(dataValue) { 111 | if size > 0 && size < 65532 { 112 | sqlType = fmt.Sprintf("varbinary(%d)", size) 113 | } else { 114 | sqlType = "longblob" 115 | } 116 | } 117 | } 118 | } 119 | 120 | if sqlType == "" { 121 | panic(fmt.Sprintf("invalid sql type %s (%s) for mysql", dataValue.Type().Name(), dataValue.Kind().String())) 122 | } 123 | 124 | if strings.TrimSpace(additionalType) == "" { 125 | return sqlType 126 | } 127 | return fmt.Sprintf("%v %v", sqlType, additionalType) 128 | } 129 | 130 | func (s mysql) RemoveIndex(tableName string, indexName string) error { 131 | _, err := s.db.Exec(fmt.Sprintf("DROP INDEX %v ON %v", indexName, s.Quote(tableName))) 132 | return err 133 | } 134 | 135 | func (s mysql) ModifyColumn(tableName string, columnName string, typ string) error { 136 | _, err := s.db.Exec(fmt.Sprintf("ALTER TABLE %v MODIFY COLUMN %v %v", tableName, columnName, typ)) 137 | return err 138 | } 139 | 140 | func (s mysql) LimitAndOffsetSQL(limit, offset interface{}) (sql string) { 141 | if limit != nil { 142 | if parsedLimit, err := strconv.ParseInt(fmt.Sprint(limit), 0, 0); err == nil && parsedLimit >= 0 { 143 | sql += fmt.Sprintf(" LIMIT %d", parsedLimit) 144 | 145 | if offset != nil { 146 | if parsedOffset, err := strconv.ParseInt(fmt.Sprint(offset), 0, 0); err == nil && parsedOffset >= 0 { 147 | sql += fmt.Sprintf(" OFFSET %d", parsedOffset) 148 | } 149 | } 150 | } 151 | } 152 | return 153 | } 154 | 155 | func (s mysql) HasForeignKey(tableName string, foreignKeyName string) bool { 156 | var count int 157 | currentDatabase, tableName := currentDatabaseAndTable(&s, tableName) 158 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA=? AND TABLE_NAME=? AND CONSTRAINT_NAME=? AND CONSTRAINT_TYPE='FOREIGN KEY'", currentDatabase, tableName, foreignKeyName).Scan(&count) 159 | return count > 0 160 | } 161 | 162 | func (s mysql) CurrentDatabase() (name string) { 163 | s.db.QueryRow("SELECT DATABASE()").Scan(&name) 164 | return 165 | } 166 | 167 | func (mysql) SelectFromDummyTable() string { 168 | return "FROM DUAL" 169 | } 170 | 171 | func (s mysql) BuildKeyName(kind, tableName string, fields ...string) string { 172 | keyName := s.commonDialect.BuildKeyName(kind, tableName, fields...) 173 | if utf8.RuneCountInString(keyName) <= 64 { 174 | return keyName 175 | } 176 | h := sha1.New() 177 | h.Write([]byte(keyName)) 178 | bs := h.Sum(nil) 179 | 180 | // sha1 is 40 characters, keep first 24 characters of destination 181 | destRunes := []rune(regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString(fields[0], "_")) 182 | if len(destRunes) > 24 { 183 | destRunes = destRunes[:24] 184 | } 185 | 186 | return fmt.Sprintf("%s%x", string(destRunes), bs) 187 | } 188 | 189 | func (mysql) DefaultValueStr() string { 190 | return "VALUES()" 191 | } 192 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialect_postgres.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "reflect" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type postgres struct { 12 | commonDialect 13 | } 14 | 15 | func init() { 16 | RegisterDialect("postgres", &postgres{}) 17 | RegisterDialect("cloudsqlpostgres", &postgres{}) 18 | } 19 | 20 | func (postgres) GetName() string { 21 | return "postgres" 22 | } 23 | 24 | func (postgres) BindVar(i int) string { 25 | return fmt.Sprintf("$%v", i) 26 | } 27 | 28 | func (s *postgres) DataTypeOf(field *StructField) string { 29 | var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) 30 | 31 | if sqlType == "" { 32 | switch dataValue.Kind() { 33 | case reflect.Bool: 34 | sqlType = "boolean" 35 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uintptr: 36 | if s.fieldCanAutoIncrement(field) { 37 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 38 | sqlType = "serial" 39 | } else { 40 | sqlType = "integer" 41 | } 42 | case reflect.Int64, reflect.Uint32, reflect.Uint64: 43 | if s.fieldCanAutoIncrement(field) { 44 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 45 | sqlType = "bigserial" 46 | } else { 47 | sqlType = "bigint" 48 | } 49 | case reflect.Float32, reflect.Float64: 50 | sqlType = "numeric" 51 | case reflect.String: 52 | if _, ok := field.TagSettingsGet("SIZE"); !ok { 53 | size = 0 // if SIZE haven't been set, use `text` as the default type, as there are no performance different 54 | } 55 | 56 | if size > 0 && size < 65532 { 57 | sqlType = fmt.Sprintf("varchar(%d)", size) 58 | } else { 59 | sqlType = "text" 60 | } 61 | case reflect.Struct: 62 | if _, ok := dataValue.Interface().(time.Time); ok { 63 | sqlType = "timestamp with time zone" 64 | } 65 | case reflect.Map: 66 | if dataValue.Type().Name() == "Hstore" { 67 | sqlType = "hstore" 68 | } 69 | default: 70 | if IsByteArrayOrSlice(dataValue) { 71 | sqlType = "bytea" 72 | 73 | if isUUID(dataValue) { 74 | sqlType = "uuid" 75 | } 76 | 77 | if isJSON(dataValue) { 78 | sqlType = "jsonb" 79 | } 80 | } 81 | } 82 | } 83 | 84 | if sqlType == "" { 85 | panic(fmt.Sprintf("invalid sql type %s (%s) for postgres", dataValue.Type().Name(), dataValue.Kind().String())) 86 | } 87 | 88 | if strings.TrimSpace(additionalType) == "" { 89 | return sqlType 90 | } 91 | return fmt.Sprintf("%v %v", sqlType, additionalType) 92 | } 93 | 94 | func (s postgres) HasIndex(tableName string, indexName string) bool { 95 | var count int 96 | s.db.QueryRow("SELECT count(*) FROM pg_indexes WHERE tablename = $1 AND indexname = $2 AND schemaname = CURRENT_SCHEMA()", tableName, indexName).Scan(&count) 97 | return count > 0 98 | } 99 | 100 | func (s postgres) HasForeignKey(tableName string, foreignKeyName string) bool { 101 | var count int 102 | s.db.QueryRow("SELECT count(con.conname) FROM pg_constraint con WHERE $1::regclass::oid = con.conrelid AND con.conname = $2 AND con.contype='f'", tableName, foreignKeyName).Scan(&count) 103 | return count > 0 104 | } 105 | 106 | func (s postgres) HasTable(tableName string) bool { 107 | var count int 108 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE table_name = $1 AND table_type = 'BASE TABLE' AND table_schema = CURRENT_SCHEMA()", tableName).Scan(&count) 109 | return count > 0 110 | } 111 | 112 | func (s postgres) HasColumn(tableName string, columnName string) bool { 113 | var count int 114 | s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.columns WHERE table_name = $1 AND column_name = $2 AND table_schema = CURRENT_SCHEMA()", tableName, columnName).Scan(&count) 115 | return count > 0 116 | } 117 | 118 | func (s postgres) CurrentDatabase() (name string) { 119 | s.db.QueryRow("SELECT CURRENT_DATABASE()").Scan(&name) 120 | return 121 | } 122 | 123 | func (s postgres) LastInsertIDReturningSuffix(tableName, key string) string { 124 | return fmt.Sprintf("RETURNING %v.%v", tableName, key) 125 | } 126 | 127 | func (postgres) SupportLastInsertID() bool { 128 | return false 129 | } 130 | 131 | func isUUID(value reflect.Value) bool { 132 | if value.Kind() != reflect.Array || value.Type().Len() != 16 { 133 | return false 134 | } 135 | typename := value.Type().Name() 136 | lower := strings.ToLower(typename) 137 | return "uuid" == lower || "guid" == lower 138 | } 139 | 140 | func isJSON(value reflect.Value) bool { 141 | _, ok := value.Interface().(json.RawMessage) 142 | return ok 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialect_sqlite3.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | type sqlite3 struct { 11 | commonDialect 12 | } 13 | 14 | func init() { 15 | RegisterDialect("sqlite3", &sqlite3{}) 16 | } 17 | 18 | func (sqlite3) GetName() string { 19 | return "sqlite3" 20 | } 21 | 22 | // Get Data Type for Sqlite Dialect 23 | func (s *sqlite3) DataTypeOf(field *StructField) string { 24 | var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) 25 | 26 | if sqlType == "" { 27 | switch dataValue.Kind() { 28 | case reflect.Bool: 29 | sqlType = "bool" 30 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: 31 | if s.fieldCanAutoIncrement(field) { 32 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 33 | sqlType = "integer primary key autoincrement" 34 | } else { 35 | sqlType = "integer" 36 | } 37 | case reflect.Int64, reflect.Uint64: 38 | if s.fieldCanAutoIncrement(field) { 39 | field.TagSettingsSet("AUTO_INCREMENT", "AUTO_INCREMENT") 40 | sqlType = "integer primary key autoincrement" 41 | } else { 42 | sqlType = "bigint" 43 | } 44 | case reflect.Float32, reflect.Float64: 45 | sqlType = "real" 46 | case reflect.String: 47 | if size > 0 && size < 65532 { 48 | sqlType = fmt.Sprintf("varchar(%d)", size) 49 | } else { 50 | sqlType = "text" 51 | } 52 | case reflect.Struct: 53 | if _, ok := dataValue.Interface().(time.Time); ok { 54 | sqlType = "datetime" 55 | } 56 | default: 57 | if IsByteArrayOrSlice(dataValue) { 58 | sqlType = "blob" 59 | } 60 | } 61 | } 62 | 63 | if sqlType == "" { 64 | panic(fmt.Sprintf("invalid sql type %s (%s) for sqlite3", dataValue.Type().Name(), dataValue.Kind().String())) 65 | } 66 | 67 | if strings.TrimSpace(additionalType) == "" { 68 | return sqlType 69 | } 70 | return fmt.Sprintf("%v %v", sqlType, additionalType) 71 | } 72 | 73 | func (s sqlite3) HasIndex(tableName string, indexName string) bool { 74 | var count int 75 | s.db.QueryRow(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND sql LIKE '%%INDEX %v ON%%'", indexName), tableName).Scan(&count) 76 | return count > 0 77 | } 78 | 79 | func (s sqlite3) HasTable(tableName string) bool { 80 | var count int 81 | s.db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?", tableName).Scan(&count) 82 | return count > 0 83 | } 84 | 85 | func (s sqlite3) HasColumn(tableName string, columnName string) bool { 86 | var count int 87 | s.db.QueryRow(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND (sql LIKE '%%\"%v\" %%' OR sql LIKE '%%%v %%');\n", columnName, columnName), tableName).Scan(&count) 88 | return count > 0 89 | } 90 | 91 | func (s sqlite3) CurrentDatabase() (name string) { 92 | var ( 93 | ifaces = make([]interface{}, 3) 94 | pointers = make([]*string, 3) 95 | i int 96 | ) 97 | for i = 0; i < 3; i++ { 98 | ifaces[i] = &pointers[i] 99 | } 100 | if err := s.db.QueryRow("PRAGMA database_list").Scan(ifaces...); err != nil { 101 | return 102 | } 103 | if pointers[1] != nil { 104 | name = *pointers[1] 105 | } 106 | return 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/dialects/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import ( 4 | "database/sql" 5 | "database/sql/driver" 6 | 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | _ "github.com/lib/pq" 11 | "github.com/lib/pq/hstore" 12 | ) 13 | 14 | type Hstore map[string]*string 15 | 16 | // Value get value of Hstore 17 | func (h Hstore) Value() (driver.Value, error) { 18 | hstore := hstore.Hstore{Map: map[string]sql.NullString{}} 19 | if len(h) == 0 { 20 | return nil, nil 21 | } 22 | 23 | for key, value := range h { 24 | var s sql.NullString 25 | if value != nil { 26 | s.String = *value 27 | s.Valid = true 28 | } 29 | hstore.Map[key] = s 30 | } 31 | return hstore.Value() 32 | } 33 | 34 | // Scan scan value into Hstore 35 | func (h *Hstore) Scan(value interface{}) error { 36 | hstore := hstore.Hstore{} 37 | 38 | if err := hstore.Scan(value); err != nil { 39 | return err 40 | } 41 | 42 | if len(hstore.Map) == 0 { 43 | return nil 44 | } 45 | 46 | *h = Hstore{} 47 | for k := range hstore.Map { 48 | if hstore.Map[k].Valid { 49 | s := hstore.Map[k].String 50 | (*h)[k] = &s 51 | } else { 52 | (*h)[k] = nil 53 | } 54 | } 55 | 56 | return nil 57 | } 58 | 59 | // Jsonb Postgresql's JSONB data type 60 | type Jsonb struct { 61 | json.RawMessage 62 | } 63 | 64 | // Value get value of Jsonb 65 | func (j Jsonb) Value() (driver.Value, error) { 66 | if len(j.RawMessage) == 0 { 67 | return nil, nil 68 | } 69 | return j.MarshalJSON() 70 | } 71 | 72 | // Scan scan value into Jsonb 73 | func (j *Jsonb) Scan(value interface{}) error { 74 | bytes, ok := value.([]byte) 75 | if !ok { 76 | return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value)) 77 | } 78 | 79 | return json.Unmarshal(bytes, j) 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | mysql: 5 | image: 'mysql:latest' 6 | ports: 7 | - 9910:3306 8 | environment: 9 | - MYSQL_DATABASE=gorm 10 | - MYSQL_USER=gorm 11 | - MYSQL_PASSWORD=gorm 12 | - MYSQL_RANDOM_ROOT_PASSWORD="yes" 13 | postgres: 14 | image: 'postgres:latest' 15 | ports: 16 | - 9920:5432 17 | environment: 18 | - POSTGRES_USER=gorm 19 | - POSTGRES_DB=gorm 20 | - POSTGRES_PASSWORD=gorm 21 | mssql: 22 | image: 'mcmoe/mssqldocker:latest' 23 | ports: 24 | - 9930:1433 25 | environment: 26 | - ACCEPT_EULA=Y 27 | - SA_PASSWORD=LoremIpsum86 28 | - MSSQL_DB=gorm 29 | - MSSQL_USER=gorm 30 | - MSSQL_PASSWORD=LoremIpsum86 31 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/errors.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | ) 7 | 8 | var ( 9 | // ErrRecordNotFound record not found error, happens when only haven't find any matched data when looking up with a struct, finding a slice won't return this error 10 | ErrRecordNotFound = errors.New("record not found") 11 | // ErrInvalidSQL invalid SQL error, happens when you passed invalid SQL 12 | ErrInvalidSQL = errors.New("invalid SQL") 13 | // ErrInvalidTransaction invalid transaction when you are trying to `Commit` or `Rollback` 14 | ErrInvalidTransaction = errors.New("no valid transaction") 15 | // ErrCantStartTransaction can't start transaction when you are trying to start one with `Begin` 16 | ErrCantStartTransaction = errors.New("can't start transaction") 17 | // ErrUnaddressable unaddressable value 18 | ErrUnaddressable = errors.New("using unaddressable value") 19 | ) 20 | 21 | // Errors contains all happened errors 22 | type Errors []error 23 | 24 | // IsRecordNotFoundError returns current error has record not found error or not 25 | func IsRecordNotFoundError(err error) bool { 26 | if errs, ok := err.(Errors); ok { 27 | for _, err := range errs { 28 | if err == ErrRecordNotFound { 29 | return true 30 | } 31 | } 32 | } 33 | return err == ErrRecordNotFound 34 | } 35 | 36 | // GetErrors gets all happened errors 37 | func (errs Errors) GetErrors() []error { 38 | return errs 39 | } 40 | 41 | // Add adds an error 42 | func (errs Errors) Add(newErrors ...error) Errors { 43 | for _, err := range newErrors { 44 | if err == nil { 45 | continue 46 | } 47 | 48 | if errors, ok := err.(Errors); ok { 49 | errs = errs.Add(errors...) 50 | } else { 51 | ok = true 52 | for _, e := range errs { 53 | if err == e { 54 | ok = false 55 | } 56 | } 57 | if ok { 58 | errs = append(errs, err) 59 | } 60 | } 61 | } 62 | return errs 63 | } 64 | 65 | // Error format happened errors 66 | func (errs Errors) Error() string { 67 | var errors = []string{} 68 | for _, e := range errs { 69 | errors = append(errors, e.Error()) 70 | } 71 | return strings.Join(errors, "; ") 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/field.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "database/sql" 5 | "database/sql/driver" 6 | "errors" 7 | "fmt" 8 | "reflect" 9 | ) 10 | 11 | // Field model field definition 12 | type Field struct { 13 | *StructField 14 | IsBlank bool 15 | Field reflect.Value 16 | } 17 | 18 | // Set set a value to the field 19 | func (field *Field) Set(value interface{}) (err error) { 20 | if !field.Field.IsValid() { 21 | return errors.New("field value not valid") 22 | } 23 | 24 | if !field.Field.CanAddr() { 25 | return ErrUnaddressable 26 | } 27 | 28 | reflectValue, ok := value.(reflect.Value) 29 | if !ok { 30 | reflectValue = reflect.ValueOf(value) 31 | } 32 | 33 | fieldValue := field.Field 34 | if reflectValue.IsValid() { 35 | if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { 36 | fieldValue.Set(reflectValue.Convert(fieldValue.Type())) 37 | } else { 38 | if fieldValue.Kind() == reflect.Ptr { 39 | if fieldValue.IsNil() { 40 | fieldValue.Set(reflect.New(field.Struct.Type.Elem())) 41 | } 42 | fieldValue = fieldValue.Elem() 43 | } 44 | 45 | if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { 46 | fieldValue.Set(reflectValue.Convert(fieldValue.Type())) 47 | } else if scanner, ok := fieldValue.Addr().Interface().(sql.Scanner); ok { 48 | v := reflectValue.Interface() 49 | if valuer, ok := v.(driver.Valuer); ok { 50 | if v, err = valuer.Value(); err == nil { 51 | err = scanner.Scan(v) 52 | } 53 | } else { 54 | err = scanner.Scan(v) 55 | } 56 | } else { 57 | err = fmt.Errorf("could not convert argument of field %s from %s to %s", field.Name, reflectValue.Type(), fieldValue.Type()) 58 | } 59 | } 60 | } else { 61 | field.Field.Set(reflect.Zero(field.Field.Type())) 62 | } 63 | 64 | field.IsBlank = isBlank(field.Field) 65 | return err 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/interface.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import "database/sql" 4 | 5 | // SQLCommon is the minimal database connection functionality gorm requires. Implemented by *sql.DB. 6 | type SQLCommon interface { 7 | Exec(query string, args ...interface{}) (sql.Result, error) 8 | Prepare(query string) (*sql.Stmt, error) 9 | Query(query string, args ...interface{}) (*sql.Rows, error) 10 | QueryRow(query string, args ...interface{}) *sql.Row 11 | } 12 | 13 | type sqlDb interface { 14 | Begin() (*sql.Tx, error) 15 | } 16 | 17 | type sqlTx interface { 18 | Commit() error 19 | Rollback() error 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/logger.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "database/sql/driver" 5 | "fmt" 6 | "log" 7 | "os" 8 | "reflect" 9 | "regexp" 10 | "strconv" 11 | "time" 12 | "unicode" 13 | ) 14 | 15 | var ( 16 | defaultLogger = Logger{log.New(os.Stdout, "\r\n", 0)} 17 | sqlRegexp = regexp.MustCompile(`\?`) 18 | numericPlaceHolderRegexp = regexp.MustCompile(`\$\d+`) 19 | ) 20 | 21 | func isPrintable(s string) bool { 22 | for _, r := range s { 23 | if !unicode.IsPrint(r) { 24 | return false 25 | } 26 | } 27 | return true 28 | } 29 | 30 | var LogFormatter = func(values ...interface{}) (messages []interface{}) { 31 | if len(values) > 1 { 32 | var ( 33 | sql string 34 | formattedValues []string 35 | level = values[0] 36 | currentTime = "\n\033[33m[" + NowFunc().Format("2006-01-02 15:04:05") + "]\033[0m" 37 | source = fmt.Sprintf("\033[35m(%v)\033[0m", values[1]) 38 | ) 39 | 40 | messages = []interface{}{source, currentTime} 41 | 42 | if level == "sql" { 43 | // duration 44 | messages = append(messages, fmt.Sprintf(" \033[36;1m[%.2fms]\033[0m ", float64(values[2].(time.Duration).Nanoseconds()/1e4)/100.0)) 45 | // sql 46 | 47 | for _, value := range values[4].([]interface{}) { 48 | indirectValue := reflect.Indirect(reflect.ValueOf(value)) 49 | if indirectValue.IsValid() { 50 | value = indirectValue.Interface() 51 | if t, ok := value.(time.Time); ok { 52 | formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05"))) 53 | } else if b, ok := value.([]byte); ok { 54 | if str := string(b); isPrintable(str) { 55 | formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str)) 56 | } else { 57 | formattedValues = append(formattedValues, "''") 58 | } 59 | } else if r, ok := value.(driver.Valuer); ok { 60 | if value, err := r.Value(); err == nil && value != nil { 61 | formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) 62 | } else { 63 | formattedValues = append(formattedValues, "NULL") 64 | } 65 | } else { 66 | formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) 67 | } 68 | } else { 69 | formattedValues = append(formattedValues, "NULL") 70 | } 71 | } 72 | 73 | // differentiate between $n placeholders or else treat like ? 74 | if numericPlaceHolderRegexp.MatchString(values[3].(string)) { 75 | sql = values[3].(string) 76 | for index, value := range formattedValues { 77 | placeholder := fmt.Sprintf(`\$%d([^\d]|$)`, index+1) 78 | sql = regexp.MustCompile(placeholder).ReplaceAllString(sql, value+"$1") 79 | } 80 | } else { 81 | formattedValuesLength := len(formattedValues) 82 | for index, value := range sqlRegexp.Split(values[3].(string), -1) { 83 | sql += value 84 | if index < formattedValuesLength { 85 | sql += formattedValues[index] 86 | } 87 | } 88 | } 89 | 90 | messages = append(messages, sql) 91 | messages = append(messages, fmt.Sprintf(" \n\033[36;31m[%v]\033[0m ", strconv.FormatInt(values[5].(int64), 10)+" rows affected or returned ")) 92 | } else { 93 | messages = append(messages, "\033[31;1m") 94 | messages = append(messages, values[2:]...) 95 | messages = append(messages, "\033[0m") 96 | } 97 | } 98 | 99 | return 100 | } 101 | 102 | type logger interface { 103 | Print(v ...interface{}) 104 | } 105 | 106 | // LogWriter log writer interface 107 | type LogWriter interface { 108 | Println(v ...interface{}) 109 | } 110 | 111 | // Logger default logger 112 | type Logger struct { 113 | LogWriter 114 | } 115 | 116 | // Print format & print log 117 | func (logger Logger) Print(values ...interface{}) { 118 | logger.Println(LogFormatter(values...)...) 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/model.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import "time" 4 | 5 | // Model base model definition, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, which could be embedded in your models 6 | // type User struct { 7 | // gorm.Model 8 | // } 9 | type Model struct { 10 | ID uint `gorm:"primary_key"` 11 | CreatedAt time.Time 12 | UpdatedAt time.Time 13 | DeletedAt *time.Time `sql:"index"` 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/naming.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | ) 7 | 8 | // Namer is a function type which is given a string and return a string 9 | type Namer func(string) string 10 | 11 | // NamingStrategy represents naming strategies 12 | type NamingStrategy struct { 13 | DB Namer 14 | Table Namer 15 | Column Namer 16 | } 17 | 18 | // TheNamingStrategy is being initialized with defaultNamingStrategy 19 | var TheNamingStrategy = &NamingStrategy{ 20 | DB: defaultNamer, 21 | Table: defaultNamer, 22 | Column: defaultNamer, 23 | } 24 | 25 | // AddNamingStrategy sets the naming strategy 26 | func AddNamingStrategy(ns *NamingStrategy) { 27 | if ns.DB == nil { 28 | ns.DB = defaultNamer 29 | } 30 | if ns.Table == nil { 31 | ns.Table = defaultNamer 32 | } 33 | if ns.Column == nil { 34 | ns.Column = defaultNamer 35 | } 36 | TheNamingStrategy = ns 37 | } 38 | 39 | // DBName alters the given name by DB 40 | func (ns *NamingStrategy) DBName(name string) string { 41 | return ns.DB(name) 42 | } 43 | 44 | // TableName alters the given name by Table 45 | func (ns *NamingStrategy) TableName(name string) string { 46 | return ns.Table(name) 47 | } 48 | 49 | // ColumnName alters the given name by Column 50 | func (ns *NamingStrategy) ColumnName(name string) string { 51 | return ns.Column(name) 52 | } 53 | 54 | // ToDBName convert string to db name 55 | func ToDBName(name string) string { 56 | return TheNamingStrategy.DBName(name) 57 | } 58 | 59 | // ToTableName convert string to table name 60 | func ToTableName(name string) string { 61 | return TheNamingStrategy.TableName(name) 62 | } 63 | 64 | // ToColumnName convert string to db name 65 | func ToColumnName(name string) string { 66 | return TheNamingStrategy.ColumnName(name) 67 | } 68 | 69 | var smap = newSafeMap() 70 | 71 | func defaultNamer(name string) string { 72 | const ( 73 | lower = false 74 | upper = true 75 | ) 76 | 77 | if v := smap.Get(name); v != "" { 78 | return v 79 | } 80 | 81 | if name == "" { 82 | return "" 83 | } 84 | 85 | var ( 86 | value = commonInitialismsReplacer.Replace(name) 87 | buf = bytes.NewBufferString("") 88 | lastCase, currCase, nextCase, nextNumber bool 89 | ) 90 | 91 | for i, v := range value[:len(value)-1] { 92 | nextCase = bool(value[i+1] >= 'A' && value[i+1] <= 'Z') 93 | nextNumber = bool(value[i+1] >= '0' && value[i+1] <= '9') 94 | 95 | if i > 0 { 96 | if currCase == upper { 97 | if lastCase == upper && (nextCase == upper || nextNumber == upper) { 98 | buf.WriteRune(v) 99 | } else { 100 | if value[i-1] != '_' && value[i+1] != '_' { 101 | buf.WriteRune('_') 102 | } 103 | buf.WriteRune(v) 104 | } 105 | } else { 106 | buf.WriteRune(v) 107 | if i == len(value)-2 && (nextCase == upper && nextNumber == lower) { 108 | buf.WriteRune('_') 109 | } 110 | } 111 | } else { 112 | currCase = upper 113 | buf.WriteRune(v) 114 | } 115 | lastCase = currCase 116 | currCase = nextCase 117 | } 118 | 119 | buf.WriteByte(value[len(value)-1]) 120 | 121 | s := strings.ToLower(buf.String()) 122 | smap.Set(name, s) 123 | return s 124 | } 125 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/search.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type search struct { 8 | db *DB 9 | whereConditions []map[string]interface{} 10 | orConditions []map[string]interface{} 11 | notConditions []map[string]interface{} 12 | havingConditions []map[string]interface{} 13 | joinConditions []map[string]interface{} 14 | initAttrs []interface{} 15 | assignAttrs []interface{} 16 | selects map[string]interface{} 17 | omits []string 18 | orders []interface{} 19 | preload []searchPreload 20 | offset interface{} 21 | limit interface{} 22 | group string 23 | tableName string 24 | raw bool 25 | Unscoped bool 26 | ignoreOrderQuery bool 27 | } 28 | 29 | type searchPreload struct { 30 | schema string 31 | conditions []interface{} 32 | } 33 | 34 | func (s *search) clone() *search { 35 | clone := *s 36 | return &clone 37 | } 38 | 39 | func (s *search) Where(query interface{}, values ...interface{}) *search { 40 | s.whereConditions = append(s.whereConditions, map[string]interface{}{"query": query, "args": values}) 41 | return s 42 | } 43 | 44 | func (s *search) Not(query interface{}, values ...interface{}) *search { 45 | s.notConditions = append(s.notConditions, map[string]interface{}{"query": query, "args": values}) 46 | return s 47 | } 48 | 49 | func (s *search) Or(query interface{}, values ...interface{}) *search { 50 | s.orConditions = append(s.orConditions, map[string]interface{}{"query": query, "args": values}) 51 | return s 52 | } 53 | 54 | func (s *search) Attrs(attrs ...interface{}) *search { 55 | s.initAttrs = append(s.initAttrs, toSearchableMap(attrs...)) 56 | return s 57 | } 58 | 59 | func (s *search) Assign(attrs ...interface{}) *search { 60 | s.assignAttrs = append(s.assignAttrs, toSearchableMap(attrs...)) 61 | return s 62 | } 63 | 64 | func (s *search) Order(value interface{}, reorder ...bool) *search { 65 | if len(reorder) > 0 && reorder[0] { 66 | s.orders = []interface{}{} 67 | } 68 | 69 | if value != nil && value != "" { 70 | s.orders = append(s.orders, value) 71 | } 72 | return s 73 | } 74 | 75 | func (s *search) Select(query interface{}, args ...interface{}) *search { 76 | s.selects = map[string]interface{}{"query": query, "args": args} 77 | return s 78 | } 79 | 80 | func (s *search) Omit(columns ...string) *search { 81 | s.omits = columns 82 | return s 83 | } 84 | 85 | func (s *search) Limit(limit interface{}) *search { 86 | s.limit = limit 87 | return s 88 | } 89 | 90 | func (s *search) Offset(offset interface{}) *search { 91 | s.offset = offset 92 | return s 93 | } 94 | 95 | func (s *search) Group(query string) *search { 96 | s.group = s.getInterfaceAsSQL(query) 97 | return s 98 | } 99 | 100 | func (s *search) Having(query interface{}, values ...interface{}) *search { 101 | if val, ok := query.(*expr); ok { 102 | s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": val.expr, "args": val.args}) 103 | } else { 104 | s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": query, "args": values}) 105 | } 106 | return s 107 | } 108 | 109 | func (s *search) Joins(query string, values ...interface{}) *search { 110 | s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values}) 111 | return s 112 | } 113 | 114 | func (s *search) Preload(schema string, values ...interface{}) *search { 115 | var preloads []searchPreload 116 | for _, preload := range s.preload { 117 | if preload.schema != schema { 118 | preloads = append(preloads, preload) 119 | } 120 | } 121 | preloads = append(preloads, searchPreload{schema, values}) 122 | s.preload = preloads 123 | return s 124 | } 125 | 126 | func (s *search) Raw(b bool) *search { 127 | s.raw = b 128 | return s 129 | } 130 | 131 | func (s *search) unscoped() *search { 132 | s.Unscoped = true 133 | return s 134 | } 135 | 136 | func (s *search) Table(name string) *search { 137 | s.tableName = name 138 | return s 139 | } 140 | 141 | func (s *search) getInterfaceAsSQL(value interface{}) (str string) { 142 | switch value.(type) { 143 | case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: 144 | str = fmt.Sprintf("%v", value) 145 | default: 146 | s.db.AddError(ErrInvalidSQL) 147 | } 148 | 149 | if str == "-1" { 150 | return "" 151 | } 152 | return 153 | } 154 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/test_all.sh: -------------------------------------------------------------------------------- 1 | dialects=("postgres" "mysql" "mssql" "sqlite") 2 | 3 | for dialect in "${dialects[@]}" ; do 4 | DEBUG=false GORM_DIALECT=${dialect} go test 5 | done 6 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/utils.go: -------------------------------------------------------------------------------- 1 | package gorm 2 | 3 | import ( 4 | "database/sql/driver" 5 | "fmt" 6 | "reflect" 7 | "regexp" 8 | "runtime" 9 | "strings" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // NowFunc returns current time, this function is exported in order to be able 15 | // to give the flexibility to the developer to customize it according to their 16 | // needs, e.g: 17 | // gorm.NowFunc = func() time.Time { 18 | // return time.Now().UTC() 19 | // } 20 | var NowFunc = func() time.Time { 21 | return time.Now() 22 | } 23 | 24 | // Copied from golint 25 | var commonInitialisms = []string{"API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SSH", "TLS", "TTL", "UID", "UI", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XSRF", "XSS"} 26 | var commonInitialismsReplacer *strings.Replacer 27 | 28 | var goSrcRegexp = regexp.MustCompile(`jinzhu/gorm(@.*)?/.*.go`) 29 | var goTestRegexp = regexp.MustCompile(`jinzhu/gorm(@.*)?/.*test.go`) 30 | 31 | func init() { 32 | var commonInitialismsForReplacer []string 33 | for _, initialism := range commonInitialisms { 34 | commonInitialismsForReplacer = append(commonInitialismsForReplacer, initialism, strings.Title(strings.ToLower(initialism))) 35 | } 36 | commonInitialismsReplacer = strings.NewReplacer(commonInitialismsForReplacer...) 37 | } 38 | 39 | type safeMap struct { 40 | m map[string]string 41 | l *sync.RWMutex 42 | } 43 | 44 | func (s *safeMap) Set(key string, value string) { 45 | s.l.Lock() 46 | defer s.l.Unlock() 47 | s.m[key] = value 48 | } 49 | 50 | func (s *safeMap) Get(key string) string { 51 | s.l.RLock() 52 | defer s.l.RUnlock() 53 | return s.m[key] 54 | } 55 | 56 | func newSafeMap() *safeMap { 57 | return &safeMap{l: new(sync.RWMutex), m: make(map[string]string)} 58 | } 59 | 60 | // SQL expression 61 | type expr struct { 62 | expr string 63 | args []interface{} 64 | } 65 | 66 | // Expr generate raw SQL expression, for example: 67 | // DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100)) 68 | func Expr(expression string, args ...interface{}) *expr { 69 | return &expr{expr: expression, args: args} 70 | } 71 | 72 | func indirect(reflectValue reflect.Value) reflect.Value { 73 | for reflectValue.Kind() == reflect.Ptr { 74 | reflectValue = reflectValue.Elem() 75 | } 76 | return reflectValue 77 | } 78 | 79 | func toQueryMarks(primaryValues [][]interface{}) string { 80 | var results []string 81 | 82 | for _, primaryValue := range primaryValues { 83 | var marks []string 84 | for range primaryValue { 85 | marks = append(marks, "?") 86 | } 87 | 88 | if len(marks) > 1 { 89 | results = append(results, fmt.Sprintf("(%v)", strings.Join(marks, ","))) 90 | } else { 91 | results = append(results, strings.Join(marks, "")) 92 | } 93 | } 94 | return strings.Join(results, ",") 95 | } 96 | 97 | func toQueryCondition(scope *Scope, columns []string) string { 98 | var newColumns []string 99 | for _, column := range columns { 100 | newColumns = append(newColumns, scope.Quote(column)) 101 | } 102 | 103 | if len(columns) > 1 { 104 | return fmt.Sprintf("(%v)", strings.Join(newColumns, ",")) 105 | } 106 | return strings.Join(newColumns, ",") 107 | } 108 | 109 | func toQueryValues(values [][]interface{}) (results []interface{}) { 110 | for _, value := range values { 111 | for _, v := range value { 112 | results = append(results, v) 113 | } 114 | } 115 | return 116 | } 117 | 118 | func fileWithLineNum() string { 119 | for i := 2; i < 15; i++ { 120 | _, file, line, ok := runtime.Caller(i) 121 | if ok && (!goSrcRegexp.MatchString(file) || goTestRegexp.MatchString(file)) { 122 | return fmt.Sprintf("%v:%v", file, line) 123 | } 124 | } 125 | return "" 126 | } 127 | 128 | func isBlank(value reflect.Value) bool { 129 | switch value.Kind() { 130 | case reflect.String: 131 | return value.Len() == 0 132 | case reflect.Bool: 133 | return !value.Bool() 134 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 135 | return value.Int() == 0 136 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 137 | return value.Uint() == 0 138 | case reflect.Float32, reflect.Float64: 139 | return value.Float() == 0 140 | case reflect.Interface, reflect.Ptr: 141 | return value.IsNil() 142 | } 143 | 144 | return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) 145 | } 146 | 147 | func toSearchableMap(attrs ...interface{}) (result interface{}) { 148 | if len(attrs) > 1 { 149 | if str, ok := attrs[0].(string); ok { 150 | result = map[string]interface{}{str: attrs[1]} 151 | } 152 | } else if len(attrs) == 1 { 153 | if attr, ok := attrs[0].(map[string]interface{}); ok { 154 | result = attr 155 | } 156 | 157 | if attr, ok := attrs[0].(interface{}); ok { 158 | result = attr 159 | } 160 | } 161 | return 162 | } 163 | 164 | func equalAsString(a interface{}, b interface{}) bool { 165 | return toString(a) == toString(b) 166 | } 167 | 168 | func toString(str interface{}) string { 169 | if values, ok := str.([]interface{}); ok { 170 | var results []string 171 | for _, value := range values { 172 | results = append(results, toString(value)) 173 | } 174 | return strings.Join(results, "_") 175 | } else if bytes, ok := str.([]byte); ok { 176 | return string(bytes) 177 | } else if reflectValue := reflect.Indirect(reflect.ValueOf(str)); reflectValue.IsValid() { 178 | return fmt.Sprintf("%v", reflectValue.Interface()) 179 | } 180 | return "" 181 | } 182 | 183 | func makeSlice(elemType reflect.Type) interface{} { 184 | if elemType.Kind() == reflect.Slice { 185 | elemType = elemType.Elem() 186 | } 187 | sliceType := reflect.SliceOf(elemType) 188 | slice := reflect.New(sliceType) 189 | slice.Elem().Set(reflect.MakeSlice(sliceType, 0, 0)) 190 | return slice.Interface() 191 | } 192 | 193 | func strInSlice(a string, list []string) bool { 194 | for _, b := range list { 195 | if b == a { 196 | return true 197 | } 198 | } 199 | return false 200 | } 201 | 202 | // getValueFromFields return given fields's value 203 | func getValueFromFields(value reflect.Value, fieldNames []string) (results []interface{}) { 204 | // If value is a nil pointer, Indirect returns a zero Value! 205 | // Therefor we need to check for a zero value, 206 | // as FieldByName could panic 207 | if indirectValue := reflect.Indirect(value); indirectValue.IsValid() { 208 | for _, fieldName := range fieldNames { 209 | if fieldValue := reflect.Indirect(indirectValue.FieldByName(fieldName)); fieldValue.IsValid() { 210 | result := fieldValue.Interface() 211 | if r, ok := result.(driver.Valuer); ok { 212 | result, _ = r.Value() 213 | } 214 | results = append(results, result) 215 | } 216 | } 217 | } 218 | return 219 | } 220 | 221 | func addExtraSpaceIfExist(str string) string { 222 | if str != "" { 223 | return " " + str 224 | } 225 | return "" 226 | } 227 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/gorm/wercker.yml: -------------------------------------------------------------------------------- 1 | # use the default golang container from Docker Hub 2 | box: golang 3 | 4 | services: 5 | - name: mariadb 6 | id: mariadb:latest 7 | env: 8 | MYSQL_DATABASE: gorm 9 | MYSQL_USER: gorm 10 | MYSQL_PASSWORD: gorm 11 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 12 | - name: mysql57 13 | id: mysql:5.7 14 | env: 15 | MYSQL_DATABASE: gorm 16 | MYSQL_USER: gorm 17 | MYSQL_PASSWORD: gorm 18 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 19 | - name: mysql56 20 | id: mysql:5.6 21 | env: 22 | MYSQL_DATABASE: gorm 23 | MYSQL_USER: gorm 24 | MYSQL_PASSWORD: gorm 25 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 26 | - name: mysql55 27 | id: mysql:5.5 28 | env: 29 | MYSQL_DATABASE: gorm 30 | MYSQL_USER: gorm 31 | MYSQL_PASSWORD: gorm 32 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 33 | - name: postgres 34 | id: postgres:latest 35 | env: 36 | POSTGRES_USER: gorm 37 | POSTGRES_PASSWORD: gorm 38 | POSTGRES_DB: gorm 39 | - name: postgres96 40 | id: postgres:9.6 41 | env: 42 | POSTGRES_USER: gorm 43 | POSTGRES_PASSWORD: gorm 44 | POSTGRES_DB: gorm 45 | - name: postgres95 46 | id: postgres:9.5 47 | env: 48 | POSTGRES_USER: gorm 49 | POSTGRES_PASSWORD: gorm 50 | POSTGRES_DB: gorm 51 | - name: postgres94 52 | id: postgres:9.4 53 | env: 54 | POSTGRES_USER: gorm 55 | POSTGRES_PASSWORD: gorm 56 | POSTGRES_DB: gorm 57 | - name: postgres93 58 | id: postgres:9.3 59 | env: 60 | POSTGRES_USER: gorm 61 | POSTGRES_PASSWORD: gorm 62 | POSTGRES_DB: gorm 63 | - name: mssql 64 | id: mcmoe/mssqldocker:latest 65 | env: 66 | ACCEPT_EULA: Y 67 | SA_PASSWORD: LoremIpsum86 68 | MSSQL_DB: gorm 69 | MSSQL_USER: gorm 70 | MSSQL_PASSWORD: LoremIpsum86 71 | 72 | # The steps that will be executed in the build pipeline 73 | build: 74 | # The steps that will be executed on build 75 | steps: 76 | # Sets the go workspace and places you package 77 | # at the right place in the workspace tree 78 | - setup-go-workspace 79 | 80 | # Gets the dependencies 81 | - script: 82 | name: go get 83 | code: | 84 | cd $WERCKER_SOURCE_DIR 85 | go version 86 | go get -t ./... 87 | 88 | # Build the project 89 | - script: 90 | name: go build 91 | code: | 92 | go build ./... 93 | 94 | # Test the project 95 | - script: 96 | name: test sqlite 97 | code: | 98 | go test ./... 99 | 100 | - script: 101 | name: test mariadb 102 | code: | 103 | GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mariadb:3306)/gorm?charset=utf8&parseTime=True" go test ./... 104 | 105 | - script: 106 | name: test mysql5.7 107 | code: | 108 | GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql57:3306)/gorm?charset=utf8&parseTime=True" go test ./... 109 | 110 | - script: 111 | name: test mysql5.6 112 | code: | 113 | GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql56:3306)/gorm?charset=utf8&parseTime=True" go test ./... 114 | 115 | - script: 116 | name: test mysql5.5 117 | code: | 118 | GORM_DIALECT=mysql GORM_DSN="gorm:gorm@tcp(mysql55:3306)/gorm?charset=utf8&parseTime=True" go test ./... 119 | 120 | - script: 121 | name: test postgres 122 | code: | 123 | GORM_DIALECT=postgres GORM_DSN="host=postgres user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... 124 | 125 | - script: 126 | name: test postgres96 127 | code: | 128 | GORM_DIALECT=postgres GORM_DSN="host=postgres96 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... 129 | 130 | - script: 131 | name: test postgres95 132 | code: | 133 | GORM_DIALECT=postgres GORM_DSN="host=postgres95 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... 134 | 135 | - script: 136 | name: test postgres94 137 | code: | 138 | GORM_DIALECT=postgres GORM_DSN="host=postgres94 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... 139 | 140 | - script: 141 | name: test postgres93 142 | code: | 143 | GORM_DIALECT=postgres GORM_DSN="host=postgres93 user=gorm password=gorm DB.name=gorm port=5432 sslmode=disable" go test ./... 144 | 145 | - script: 146 | name: test mssql 147 | code: | 148 | GORM_DIALECT=mssql GORM_DSN="sqlserver://gorm:LoremIpsum86@mssql:1433?database=gorm" go test ./... 149 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/inflection/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 - Jinzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/inflection/README.md: -------------------------------------------------------------------------------- 1 | # Inflection 2 | 3 | Inflection pluralizes and singularizes English nouns 4 | 5 | [![wercker status](https://app.wercker.com/status/f8c7432b097d1f4ce636879670be0930/s/master "wercker status")](https://app.wercker.com/project/byKey/f8c7432b097d1f4ce636879670be0930) 6 | 7 | ## Basic Usage 8 | 9 | ```go 10 | inflection.Plural("person") => "people" 11 | inflection.Plural("Person") => "People" 12 | inflection.Plural("PERSON") => "PEOPLE" 13 | inflection.Plural("bus") => "buses" 14 | inflection.Plural("BUS") => "BUSES" 15 | inflection.Plural("Bus") => "Buses" 16 | 17 | inflection.Singular("people") => "person" 18 | inflection.Singular("People") => "Person" 19 | inflection.Singular("PEOPLE") => "PERSON" 20 | inflection.Singular("buses") => "bus" 21 | inflection.Singular("BUSES") => "BUS" 22 | inflection.Singular("Buses") => "Bus" 23 | 24 | inflection.Plural("FancyPerson") => "FancyPeople" 25 | inflection.Singular("FancyPeople") => "FancyPerson" 26 | ``` 27 | 28 | ## Register Rules 29 | 30 | Standard rules are from Rails's ActiveSupport (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflections.rb) 31 | 32 | If you want to register more rules, follow: 33 | 34 | ``` 35 | inflection.AddUncountable("fish") 36 | inflection.AddIrregular("person", "people") 37 | inflection.AddPlural("(bu)s$", "${1}ses") # "bus" => "buses" / "BUS" => "BUSES" / "Bus" => "Buses" 38 | inflection.AddSingular("(bus)(es)?$", "${1}") # "buses" => "bus" / "Buses" => "Bus" / "BUSES" => "BUS" 39 | ``` 40 | 41 | ## Contributing 42 | 43 | You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do. 44 | 45 | ## Author 46 | 47 | **jinzhu** 48 | 49 | * 50 | * 51 | * 52 | 53 | ## License 54 | 55 | Released under the [MIT License](http://www.opensource.org/licenses/MIT). 56 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/inflection/wercker.yml: -------------------------------------------------------------------------------- 1 | box: golang 2 | 3 | build: 4 | steps: 5 | - setup-go-workspace 6 | 7 | # Gets the dependencies 8 | - script: 9 | name: go get 10 | code: | 11 | go get 12 | 13 | # Build the project 14 | - script: 15 | name: go build 16 | code: | 17 | go build ./... 18 | 19 | # Test the project 20 | - script: 21 | name: go test 22 | code: | 23 | go test ./... 24 | -------------------------------------------------------------------------------- /vendor/github.com/joho/godotenv/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /vendor/github.com/joho/godotenv/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.x 5 | 6 | os: 7 | - linux 8 | - osx 9 | -------------------------------------------------------------------------------- /vendor/github.com/joho/godotenv/LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 John Barton 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /vendor/github.com/joho/godotenv/README.md: -------------------------------------------------------------------------------- 1 | # GoDotEnv [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4?svg=true)](https://ci.appveyor.com/project/joho/godotenv) [![Go Report Card](https://goreportcard.com/badge/github.com/joho/godotenv)](https://goreportcard.com/report/github.com/joho/godotenv) 2 | 3 | A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file) 4 | 5 | From the original Library: 6 | 7 | > Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables. 8 | > 9 | > But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped. 10 | 11 | It can be used as a library (for loading in env for your own daemons etc) or as a bin command. 12 | 13 | There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows. 14 | 15 | ## Installation 16 | 17 | As a library 18 | 19 | ```shell 20 | go get github.com/joho/godotenv 21 | ``` 22 | 23 | or if you want to use it as a bin command 24 | ```shell 25 | go get github.com/joho/godotenv/cmd/godotenv 26 | ``` 27 | 28 | ## Usage 29 | 30 | Add your application configuration to your `.env` file in the root of your project: 31 | 32 | ```shell 33 | S3_BUCKET=YOURS3BUCKET 34 | SECRET_KEY=YOURSECRETKEYGOESHERE 35 | ``` 36 | 37 | Then in your Go app you can do something like 38 | 39 | ```go 40 | package main 41 | 42 | import ( 43 | "github.com/joho/godotenv" 44 | "log" 45 | "os" 46 | ) 47 | 48 | func main() { 49 | err := godotenv.Load() 50 | if err != nil { 51 | log.Fatal("Error loading .env file") 52 | } 53 | 54 | s3Bucket := os.Getenv("S3_BUCKET") 55 | secretKey := os.Getenv("SECRET_KEY") 56 | 57 | // now do something with s3 or whatever 58 | } 59 | ``` 60 | 61 | If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import 62 | 63 | ```go 64 | import _ "github.com/joho/godotenv/autoload" 65 | ``` 66 | 67 | While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit 68 | 69 | ```go 70 | _ = godotenv.Load("somerandomfile") 71 | _ = godotenv.Load("filenumberone.env", "filenumbertwo.env") 72 | ``` 73 | 74 | If you want to be really fancy with your env file you can do comments and exports (below is a valid env file) 75 | 76 | ```shell 77 | # I am a comment and that is OK 78 | SOME_VAR=someval 79 | FOO=BAR # comments at line end are OK too 80 | export BAR=BAZ 81 | ``` 82 | 83 | Or finally you can do YAML(ish) style 84 | 85 | ```yaml 86 | FOO: bar 87 | BAR: baz 88 | ``` 89 | 90 | as a final aside, if you don't want godotenv munging your env you can just get a map back instead 91 | 92 | ```go 93 | var myEnv map[string]string 94 | myEnv, err := godotenv.Read() 95 | 96 | s3Bucket := myEnv["S3_BUCKET"] 97 | ``` 98 | 99 | ... or from an `io.Reader` instead of a local file 100 | 101 | ```go 102 | reader := getRemoteFile() 103 | myEnv, err := godotenv.Parse(reader) 104 | ``` 105 | 106 | ... or from a `string` if you so desire 107 | 108 | ```go 109 | content := getRemoteFileContent() 110 | myEnv, err := godotenv.Unmarshal(content) 111 | ``` 112 | 113 | ### Command Mode 114 | 115 | Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH` 116 | 117 | ``` 118 | godotenv -f /some/path/to/.env some_command with some args 119 | ``` 120 | 121 | If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD` 122 | 123 | ### Writing Env Files 124 | 125 | Godotenv can also write a map representing the environment to a correctly-formatted and escaped file 126 | 127 | ```go 128 | env, err := godotenv.Unmarshal("KEY=value") 129 | err := godotenv.Write(env, "./.env") 130 | ``` 131 | 132 | ... or to a string 133 | 134 | ```go 135 | env, err := godotenv.Unmarshal("KEY=value") 136 | content, err := godotenv.Marshal(env) 137 | ``` 138 | 139 | ## Contributing 140 | 141 | Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases. 142 | 143 | *code changes without tests will not be accepted* 144 | 145 | 1. Fork it 146 | 2. Create your feature branch (`git checkout -b my-new-feature`) 147 | 3. Commit your changes (`git commit -am 'Added some feature'`) 148 | 4. Push to the branch (`git push origin my-new-feature`) 149 | 5. Create new Pull Request 150 | 151 | ## Releases 152 | 153 | Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`. 154 | 155 | Use [annotated tags for all releases](https://github.com/joho/godotenv/issues/30). Example `git tag -a v1.2.1` 156 | 157 | ## CI 158 | 159 | Linux: [![Build Status](https://travis-ci.org/joho/godotenv.svg?branch=master)](https://travis-ci.org/joho/godotenv) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4)](https://ci.appveyor.com/project/joho/godotenv) 160 | 161 | ## Who? 162 | 163 | The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library. 164 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | *.test 3 | *~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | client_configure() { 6 | sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key 7 | } 8 | 9 | pgdg_repository() { 10 | local sourcelist='sources.list.d/postgresql.list' 11 | 12 | curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - 13 | echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" 14 | sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update 15 | } 16 | 17 | postgresql_configure() { 18 | sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config 19 | local all all trust 20 | hostnossl all pqgossltest 127.0.0.1/32 reject 21 | hostnossl all pqgosslcert 127.0.0.1/32 reject 22 | hostssl all pqgossltest 127.0.0.1/32 trust 23 | hostssl all pqgosslcert 127.0.0.1/32 cert 24 | host all all 127.0.0.1/32 trust 25 | hostnossl all pqgossltest ::1/128 reject 26 | hostnossl all pqgosslcert ::1/128 reject 27 | hostssl all pqgossltest ::1/128 trust 28 | hostssl all pqgosslcert ::1/128 cert 29 | host all all ::1/128 trust 30 | config 31 | 32 | xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates 33 | certs/root.crt 34 | certs/server.crt 35 | certs/server.key 36 | certificates 37 | 38 | sort -VCu <<-versions || 39 | $PGVERSION 40 | 9.2 41 | versions 42 | sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config 43 | ssl_ca_file = 'root.crt' 44 | ssl_cert_file = 'server.crt' 45 | ssl_key_file = 'server.key' 46 | config 47 | 48 | echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null 49 | 50 | sudo service postgresql restart 51 | } 52 | 53 | postgresql_install() { 54 | xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages 55 | postgresql-$PGVERSION 56 | postgresql-server-dev-$PGVERSION 57 | postgresql-contrib-$PGVERSION 58 | packages 59 | } 60 | 61 | postgresql_uninstall() { 62 | sudo service postgresql stop 63 | xargs sudo apt-get -y --purge remove <<-packages 64 | libpq-dev 65 | libpq5 66 | postgresql 67 | postgresql-client-common 68 | postgresql-common 69 | packages 70 | sudo rm -rf /var/lib/postgresql 71 | } 72 | 73 | megacheck_install() { 74 | # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous 75 | # new error messages in old code. 76 | go get -d honnef.co/go/tools/... 77 | git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION 78 | go install honnef.co/go/tools/cmd/megacheck 79 | megacheck --version 80 | } 81 | 82 | golint_install() { 83 | go get golang.org/x/lint/golint 84 | } 85 | 86 | $1 87 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.9.x 5 | - 1.10.x 6 | - 1.11.x 7 | - master 8 | 9 | sudo: true 10 | 11 | env: 12 | global: 13 | - PGUSER=postgres 14 | - PQGOSSLTESTS=1 15 | - PQSSLCERTTEST_PATH=$PWD/certs 16 | - PGHOST=127.0.0.1 17 | - MEGACHECK_VERSION=2017.2.2 18 | matrix: 19 | - PGVERSION=10 20 | - PGVERSION=9.6 21 | - PGVERSION=9.5 22 | - PGVERSION=9.4 23 | - PGVERSION=9.3 24 | - PGVERSION=9.2 25 | - PGVERSION=9.1 26 | - PGVERSION=9.0 27 | 28 | before_install: 29 | - ./.travis.sh postgresql_uninstall 30 | - ./.travis.sh pgdg_repository 31 | - ./.travis.sh postgresql_install 32 | - ./.travis.sh postgresql_configure 33 | - ./.travis.sh client_configure 34 | - ./.travis.sh megacheck_install 35 | - ./.travis.sh golint_install 36 | - go get golang.org/x/tools/cmd/goimports 37 | 38 | before_script: 39 | - createdb pqgotest 40 | - createuser -DRS pqgossltest 41 | - createuser -DRS pqgosslcert 42 | 43 | script: 44 | - > 45 | goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' 46 | - go vet ./... 47 | - megacheck -go 1.9 ./... 48 | - golint ./... 49 | - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... 50 | - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... 51 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to pq 2 | 3 | `pq` has a backlog of pull requests, but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | ### Patch review 10 | 11 | Help review existing open pull requests by commenting on the code or 12 | proposed functionality. 13 | 14 | ### Bug reports 15 | 16 | We appreciate any bug reports, but especially ones with self-contained 17 | (doesn't depend on code outside of pq), minimal (can't be simplified 18 | further) test cases. It's especially helpful if you can submit a pull 19 | request with just the failing test case (you'll probably want to 20 | pattern it after the tests in 21 | [conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). 22 | 23 | ### New functionality 24 | 25 | There are a number of pending patches for new functionality, so 26 | additional feature patches will take a while to merge. Still, patches 27 | are generally reviewed based on usefulness and complexity in addition 28 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 29 | free to open an issue discussion your proposed patch beforehand. 30 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013, 'pq' Contributors 2 | Portions Copyright (C) 2011 Blake Mizerany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/README.md: -------------------------------------------------------------------------------- 1 | # pq - A pure Go postgres driver for Go's database/sql package 2 | 3 | [![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq) 4 | [![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) 5 | 6 | ## Install 7 | 8 | go get github.com/lib/pq 9 | 10 | ## Docs 11 | 12 | For detailed documentation and basic usage examples, please see the package 13 | documentation at . 14 | 15 | ## Tests 16 | 17 | `go test` is used for testing. See [TESTS.md](TESTS.md) for more details. 18 | 19 | ## Features 20 | 21 | * SSL 22 | * Handles bad connections for `database/sql` 23 | * Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) 24 | * Scan binary blobs correctly (i.e. `bytea`) 25 | * Package for `hstore` support 26 | * COPY FROM support 27 | * pq.ParseURL for converting urls to connection strings for sql.Open. 28 | * Many libpq compatible environment variables 29 | * Unix socket support 30 | * Notifications: `LISTEN`/`NOTIFY` 31 | * pgpass support 32 | 33 | ## Future / Things you can help with 34 | 35 | * Better COPY FROM / COPY TO (see discussion in #181) 36 | 37 | ## Thank you (alphabetical) 38 | 39 | Some of these contributors are from the original library `bmizerany/pq.go` whose 40 | code still exists in here. 41 | 42 | * Andy Balholm (andybalholm) 43 | * Ben Berkert (benburkert) 44 | * Benjamin Heatwole (bheatwole) 45 | * Bill Mill (llimllib) 46 | * Bjørn Madsen (aeons) 47 | * Blake Gentry (bgentry) 48 | * Brad Fitzpatrick (bradfitz) 49 | * Charlie Melbye (cmelbye) 50 | * Chris Bandy (cbandy) 51 | * Chris Gilling (cgilling) 52 | * Chris Walsh (cwds) 53 | * Dan Sosedoff (sosedoff) 54 | * Daniel Farina (fdr) 55 | * Eric Chlebek (echlebek) 56 | * Eric Garrido (minusnine) 57 | * Eric Urban (hydrogen18) 58 | * Everyone at The Go Team 59 | * Evan Shaw (edsrzf) 60 | * Ewan Chou (coocood) 61 | * Fazal Majid (fazalmajid) 62 | * Federico Romero (federomero) 63 | * Fumin (fumin) 64 | * Gary Burd (garyburd) 65 | * Heroku (heroku) 66 | * James Pozdena (jpoz) 67 | * Jason McVetta (jmcvetta) 68 | * Jeremy Jay (pbnjay) 69 | * Joakim Sernbrant (serbaut) 70 | * John Gallagher (jgallagher) 71 | * Jonathan Rudenberg (titanous) 72 | * Joël Stemmer (jstemmer) 73 | * Kamil Kisiel (kisielk) 74 | * Kelly Dunn (kellydunn) 75 | * Keith Rarick (kr) 76 | * Kir Shatrov (kirs) 77 | * Lann Martin (lann) 78 | * Maciek Sakrejda (uhoh-itsmaciek) 79 | * Marc Brinkmann (mbr) 80 | * Marko Tiikkaja (johto) 81 | * Matt Newberry (MattNewberry) 82 | * Matt Robenolt (mattrobenolt) 83 | * Martin Olsen (martinolsen) 84 | * Mike Lewis (mikelikespie) 85 | * Nicolas Patry (Narsil) 86 | * Oliver Tonnhofer (olt) 87 | * Patrick Hayes (phayes) 88 | * Paul Hammond (paulhammond) 89 | * Ryan Smith (ryandotsmith) 90 | * Samuel Stauffer (samuel) 91 | * Timothée Peignier (cyberdelia) 92 | * Travis Cline (tmc) 93 | * TruongSinh Tran-Nguyen (truongsinh) 94 | * Yaismel Miranda (ympons) 95 | * notedit (notedit) 96 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/TESTS.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | ## Running Tests 4 | 5 | `go test` is used for testing. A running PostgreSQL 6 | server is required, with the ability to log in. The 7 | database to connect to test with is "pqgotest," on 8 | "localhost" but these can be overridden using [environment 9 | variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html). 10 | 11 | Example: 12 | 13 | PGHOST=/run/postgresql go test 14 | 15 | ## Benchmarks 16 | 17 | A benchmark suite can be run as part of the tests: 18 | 19 | go test -bench . 20 | 21 | ## Example setup (Docker) 22 | 23 | Run a postgres container: 24 | 25 | ``` 26 | docker run --expose 5432:5432 postgres 27 | ``` 28 | 29 | Run tests: 30 | 31 | ``` 32 | PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test 33 | ``` 34 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/buf.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | 7 | "github.com/lib/pq/oid" 8 | ) 9 | 10 | type readBuf []byte 11 | 12 | func (b *readBuf) int32() (n int) { 13 | n = int(int32(binary.BigEndian.Uint32(*b))) 14 | *b = (*b)[4:] 15 | return 16 | } 17 | 18 | func (b *readBuf) oid() (n oid.Oid) { 19 | n = oid.Oid(binary.BigEndian.Uint32(*b)) 20 | *b = (*b)[4:] 21 | return 22 | } 23 | 24 | // N.B: this is actually an unsigned 16-bit integer, unlike int32 25 | func (b *readBuf) int16() (n int) { 26 | n = int(binary.BigEndian.Uint16(*b)) 27 | *b = (*b)[2:] 28 | return 29 | } 30 | 31 | func (b *readBuf) string() string { 32 | i := bytes.IndexByte(*b, 0) 33 | if i < 0 { 34 | errorf("invalid message format; expected string terminator") 35 | } 36 | s := (*b)[:i] 37 | *b = (*b)[i+1:] 38 | return string(s) 39 | } 40 | 41 | func (b *readBuf) next(n int) (v []byte) { 42 | v = (*b)[:n] 43 | *b = (*b)[n:] 44 | return 45 | } 46 | 47 | func (b *readBuf) byte() byte { 48 | return b.next(1)[0] 49 | } 50 | 51 | type writeBuf struct { 52 | buf []byte 53 | pos int 54 | } 55 | 56 | func (b *writeBuf) int32(n int) { 57 | x := make([]byte, 4) 58 | binary.BigEndian.PutUint32(x, uint32(n)) 59 | b.buf = append(b.buf, x...) 60 | } 61 | 62 | func (b *writeBuf) int16(n int) { 63 | x := make([]byte, 2) 64 | binary.BigEndian.PutUint16(x, uint16(n)) 65 | b.buf = append(b.buf, x...) 66 | } 67 | 68 | func (b *writeBuf) string(s string) { 69 | b.buf = append(b.buf, (s + "\000")...) 70 | } 71 | 72 | func (b *writeBuf) byte(c byte) { 73 | b.buf = append(b.buf, c) 74 | } 75 | 76 | func (b *writeBuf) bytes(v []byte) { 77 | b.buf = append(b.buf, v...) 78 | } 79 | 80 | func (b *writeBuf) wrap() []byte { 81 | p := b.buf[b.pos:] 82 | binary.BigEndian.PutUint32(p, uint32(len(p))) 83 | return b.buf 84 | } 85 | 86 | func (b *writeBuf) next(c byte) { 87 | p := b.buf[b.pos:] 88 | binary.BigEndian.PutUint32(p, uint32(len(p))) 89 | b.pos = len(b.buf) + 1 90 | b.buf = append(b.buf, c, 0, 0, 0, 0) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/conn_go18.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "database/sql/driver" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "time" 11 | ) 12 | 13 | // Implement the "QueryerContext" interface 14 | func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 15 | list := make([]driver.Value, len(args)) 16 | for i, nv := range args { 17 | list[i] = nv.Value 18 | } 19 | finish := cn.watchCancel(ctx) 20 | r, err := cn.query(query, list) 21 | if err != nil { 22 | if finish != nil { 23 | finish() 24 | } 25 | return nil, err 26 | } 27 | r.finish = finish 28 | return r, nil 29 | } 30 | 31 | // Implement the "ExecerContext" interface 32 | func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 33 | list := make([]driver.Value, len(args)) 34 | for i, nv := range args { 35 | list[i] = nv.Value 36 | } 37 | 38 | if finish := cn.watchCancel(ctx); finish != nil { 39 | defer finish() 40 | } 41 | 42 | return cn.Exec(query, list) 43 | } 44 | 45 | // Implement the "ConnBeginTx" interface 46 | func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 47 | var mode string 48 | 49 | switch sql.IsolationLevel(opts.Isolation) { 50 | case sql.LevelDefault: 51 | // Don't touch mode: use the server's default 52 | case sql.LevelReadUncommitted: 53 | mode = " ISOLATION LEVEL READ UNCOMMITTED" 54 | case sql.LevelReadCommitted: 55 | mode = " ISOLATION LEVEL READ COMMITTED" 56 | case sql.LevelRepeatableRead: 57 | mode = " ISOLATION LEVEL REPEATABLE READ" 58 | case sql.LevelSerializable: 59 | mode = " ISOLATION LEVEL SERIALIZABLE" 60 | default: 61 | return nil, fmt.Errorf("pq: isolation level not supported: %d", opts.Isolation) 62 | } 63 | 64 | if opts.ReadOnly { 65 | mode += " READ ONLY" 66 | } else { 67 | mode += " READ WRITE" 68 | } 69 | 70 | tx, err := cn.begin(mode) 71 | if err != nil { 72 | return nil, err 73 | } 74 | cn.txnFinish = cn.watchCancel(ctx) 75 | return tx, nil 76 | } 77 | 78 | func (cn *conn) Ping(ctx context.Context) error { 79 | if finish := cn.watchCancel(ctx); finish != nil { 80 | defer finish() 81 | } 82 | rows, err := cn.simpleQuery("SELECT 'lib/pq ping test';") 83 | if err != nil { 84 | return driver.ErrBadConn // https://golang.org/pkg/database/sql/driver/#Pinger 85 | } 86 | rows.Close() 87 | return nil 88 | } 89 | 90 | func (cn *conn) watchCancel(ctx context.Context) func() { 91 | if done := ctx.Done(); done != nil { 92 | finished := make(chan struct{}) 93 | go func() { 94 | select { 95 | case <-done: 96 | // At this point the function level context is canceled, 97 | // so it must not be used for the additional network 98 | // request to cancel the query. 99 | // Create a new context to pass into the dial. 100 | ctxCancel, cancel := context.WithTimeout(context.Background(), time.Second*10) 101 | defer cancel() 102 | 103 | _ = cn.cancel(ctxCancel) 104 | finished <- struct{}{} 105 | case <-finished: 106 | } 107 | }() 108 | return func() { 109 | select { 110 | case <-finished: 111 | case finished <- struct{}{}: 112 | } 113 | } 114 | } 115 | return nil 116 | } 117 | 118 | func (cn *conn) cancel(ctx context.Context) error { 119 | c, err := dial(ctx, cn.dialer, cn.opts) 120 | if err != nil { 121 | return err 122 | } 123 | defer c.Close() 124 | 125 | { 126 | can := conn{ 127 | c: c, 128 | } 129 | err = can.ssl(cn.opts) 130 | if err != nil { 131 | return err 132 | } 133 | 134 | w := can.writeBuf(0) 135 | w.int32(80877102) // cancel request code 136 | w.int32(cn.processID) 137 | w.int32(cn.secretKey) 138 | 139 | if err := can.sendStartupPacket(w); err != nil { 140 | return err 141 | } 142 | } 143 | 144 | // Read until EOF to ensure that the server received the cancel. 145 | { 146 | _, err := io.Copy(ioutil.Discard, c) 147 | return err 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/connector.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "context" 5 | "database/sql/driver" 6 | "errors" 7 | "fmt" 8 | "os" 9 | "strings" 10 | ) 11 | 12 | // Connector represents a fixed configuration for the pq driver with a given 13 | // name. Connector satisfies the database/sql/driver Connector interface and 14 | // can be used to create any number of DB Conn's via the database/sql OpenDB 15 | // function. 16 | // 17 | // See https://golang.org/pkg/database/sql/driver/#Connector. 18 | // See https://golang.org/pkg/database/sql/#OpenDB. 19 | type Connector struct { 20 | opts values 21 | dialer Dialer 22 | } 23 | 24 | // Connect returns a connection to the database using the fixed configuration 25 | // of this Connector. Context is not used. 26 | func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { 27 | return c.open(ctx) 28 | } 29 | 30 | // Driver returnst the underlying driver of this Connector. 31 | func (c *Connector) Driver() driver.Driver { 32 | return &Driver{} 33 | } 34 | 35 | // NewConnector returns a connector for the pq driver in a fixed configuration 36 | // with the given dsn. The returned connector can be used to create any number 37 | // of equivalent Conn's. The returned connector is intended to be used with 38 | // database/sql.OpenDB. 39 | // 40 | // See https://golang.org/pkg/database/sql/driver/#Connector. 41 | // See https://golang.org/pkg/database/sql/#OpenDB. 42 | func NewConnector(dsn string) (*Connector, error) { 43 | var err error 44 | o := make(values) 45 | 46 | // A number of defaults are applied here, in this order: 47 | // 48 | // * Very low precedence defaults applied in every situation 49 | // * Environment variables 50 | // * Explicitly passed connection information 51 | o["host"] = "localhost" 52 | o["port"] = "5432" 53 | // N.B.: Extra float digits should be set to 3, but that breaks 54 | // Postgres 8.4 and older, where the max is 2. 55 | o["extra_float_digits"] = "2" 56 | for k, v := range parseEnviron(os.Environ()) { 57 | o[k] = v 58 | } 59 | 60 | if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") { 61 | dsn, err = ParseURL(dsn) 62 | if err != nil { 63 | return nil, err 64 | } 65 | } 66 | 67 | if err := parseOpts(dsn, o); err != nil { 68 | return nil, err 69 | } 70 | 71 | // Use the "fallback" application name if necessary 72 | if fallback, ok := o["fallback_application_name"]; ok { 73 | if _, ok := o["application_name"]; !ok { 74 | o["application_name"] = fallback 75 | } 76 | } 77 | 78 | // We can't work with any client_encoding other than UTF-8 currently. 79 | // However, we have historically allowed the user to set it to UTF-8 80 | // explicitly, and there's no reason to break such programs, so allow that. 81 | // Note that the "options" setting could also set client_encoding, but 82 | // parsing its value is not worth it. Instead, we always explicitly send 83 | // client_encoding as a separate run-time parameter, which should override 84 | // anything set in options. 85 | if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) { 86 | return nil, errors.New("client_encoding must be absent or 'UTF8'") 87 | } 88 | o["client_encoding"] = "UTF8" 89 | // DateStyle needs a similar treatment. 90 | if datestyle, ok := o["datestyle"]; ok { 91 | if datestyle != "ISO, MDY" { 92 | return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle) 93 | } 94 | } else { 95 | o["datestyle"] = "ISO, MDY" 96 | } 97 | 98 | // If a user is not provided by any other means, the last 99 | // resort is to use the current operating system provided user 100 | // name. 101 | if _, ok := o["user"]; !ok { 102 | u, err := userCurrent() 103 | if err != nil { 104 | return nil, err 105 | } 106 | o["user"] = u 107 | } 108 | 109 | return &Connector{opts: o, dialer: defaultDialer{}}, nil 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/lib/pq 2 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/hstore/hstore.go: -------------------------------------------------------------------------------- 1 | package hstore 2 | 3 | import ( 4 | "database/sql" 5 | "database/sql/driver" 6 | "strings" 7 | ) 8 | 9 | // Hstore is a wrapper for transferring Hstore values back and forth easily. 10 | type Hstore struct { 11 | Map map[string]sql.NullString 12 | } 13 | 14 | // escapes and quotes hstore keys/values 15 | // s should be a sql.NullString or string 16 | func hQuote(s interface{}) string { 17 | var str string 18 | switch v := s.(type) { 19 | case sql.NullString: 20 | if !v.Valid { 21 | return "NULL" 22 | } 23 | str = v.String 24 | case string: 25 | str = v 26 | default: 27 | panic("not a string or sql.NullString") 28 | } 29 | 30 | str = strings.Replace(str, "\\", "\\\\", -1) 31 | return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"` 32 | } 33 | 34 | // Scan implements the Scanner interface. 35 | // 36 | // Note h.Map is reallocated before the scan to clear existing values. If the 37 | // hstore column's database value is NULL, then h.Map is set to nil instead. 38 | func (h *Hstore) Scan(value interface{}) error { 39 | if value == nil { 40 | h.Map = nil 41 | return nil 42 | } 43 | h.Map = make(map[string]sql.NullString) 44 | var b byte 45 | pair := [][]byte{{}, {}} 46 | pi := 0 47 | inQuote := false 48 | didQuote := false 49 | sawSlash := false 50 | bindex := 0 51 | for bindex, b = range value.([]byte) { 52 | if sawSlash { 53 | pair[pi] = append(pair[pi], b) 54 | sawSlash = false 55 | continue 56 | } 57 | 58 | switch b { 59 | case '\\': 60 | sawSlash = true 61 | continue 62 | case '"': 63 | inQuote = !inQuote 64 | if !didQuote { 65 | didQuote = true 66 | } 67 | continue 68 | default: 69 | if !inQuote { 70 | switch b { 71 | case ' ', '\t', '\n', '\r': 72 | continue 73 | case '=': 74 | continue 75 | case '>': 76 | pi = 1 77 | didQuote = false 78 | continue 79 | case ',': 80 | s := string(pair[1]) 81 | if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { 82 | h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} 83 | } else { 84 | h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} 85 | } 86 | pair[0] = []byte{} 87 | pair[1] = []byte{} 88 | pi = 0 89 | continue 90 | } 91 | } 92 | } 93 | pair[pi] = append(pair[pi], b) 94 | } 95 | if bindex > 0 { 96 | s := string(pair[1]) 97 | if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { 98 | h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} 99 | } else { 100 | h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} 101 | } 102 | } 103 | return nil 104 | } 105 | 106 | // Value implements the driver Valuer interface. Note if h.Map is nil, the 107 | // database column value will be set to NULL. 108 | func (h Hstore) Value() (driver.Value, error) { 109 | if h.Map == nil { 110 | return nil, nil 111 | } 112 | parts := []string{} 113 | for key, val := range h.Map { 114 | thispart := hQuote(key) + "=>" + hQuote(val) 115 | parts = append(parts, thispart) 116 | } 117 | return []byte(strings.Join(parts, ",")), nil 118 | } 119 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/doc.go: -------------------------------------------------------------------------------- 1 | // Package oid contains OID constants 2 | // as defined by the Postgres server. 3 | package oid 4 | 5 | // Oid is a Postgres Object ID. 6 | type Oid uint32 7 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Generate the table of OID values 4 | // Run with 'go run gen.go'. 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "fmt" 10 | "log" 11 | "os" 12 | "os/exec" 13 | "strings" 14 | 15 | _ "github.com/lib/pq" 16 | ) 17 | 18 | // OID represent a postgres Object Identifier Type. 19 | type OID struct { 20 | ID int 21 | Type string 22 | } 23 | 24 | // Name returns an upper case version of the oid type. 25 | func (o OID) Name() string { 26 | return strings.ToUpper(o.Type) 27 | } 28 | 29 | func main() { 30 | datname := os.Getenv("PGDATABASE") 31 | sslmode := os.Getenv("PGSSLMODE") 32 | 33 | if datname == "" { 34 | os.Setenv("PGDATABASE", "pqgotest") 35 | } 36 | 37 | if sslmode == "" { 38 | os.Setenv("PGSSLMODE", "disable") 39 | } 40 | 41 | db, err := sql.Open("postgres", "") 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | rows, err := db.Query(` 46 | SELECT typname, oid 47 | FROM pg_type WHERE oid < 10000 48 | ORDER BY oid; 49 | `) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | oids := make([]*OID, 0) 54 | for rows.Next() { 55 | var oid OID 56 | if err = rows.Scan(&oid.Type, &oid.ID); err != nil { 57 | log.Fatal(err) 58 | } 59 | oids = append(oids, &oid) 60 | } 61 | if err = rows.Err(); err != nil { 62 | log.Fatal(err) 63 | } 64 | cmd := exec.Command("gofmt") 65 | cmd.Stderr = os.Stderr 66 | w, err := cmd.StdinPipe() 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | f, err := os.Create("types.go") 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | cmd.Stdout = f 75 | err = cmd.Start() 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.") 80 | fmt.Fprintln(w, "\npackage oid") 81 | fmt.Fprintln(w, "const (") 82 | for _, oid := range oids { 83 | fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID) 84 | } 85 | fmt.Fprintln(w, ")") 86 | fmt.Fprintln(w, "var TypeName = map[Oid]string{") 87 | for _, oid := range oids { 88 | fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name()) 89 | } 90 | fmt.Fprintln(w, "}") 91 | w.Close() 92 | cmd.Wait() 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/rows.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "math" 5 | "reflect" 6 | "time" 7 | 8 | "github.com/lib/pq/oid" 9 | ) 10 | 11 | const headerSize = 4 12 | 13 | type fieldDesc struct { 14 | // The object ID of the data type. 15 | OID oid.Oid 16 | // The data type size (see pg_type.typlen). 17 | // Note that negative values denote variable-width types. 18 | Len int 19 | // The type modifier (see pg_attribute.atttypmod). 20 | // The meaning of the modifier is type-specific. 21 | Mod int 22 | } 23 | 24 | func (fd fieldDesc) Type() reflect.Type { 25 | switch fd.OID { 26 | case oid.T_int8: 27 | return reflect.TypeOf(int64(0)) 28 | case oid.T_int4: 29 | return reflect.TypeOf(int32(0)) 30 | case oid.T_int2: 31 | return reflect.TypeOf(int16(0)) 32 | case oid.T_varchar, oid.T_text: 33 | return reflect.TypeOf("") 34 | case oid.T_bool: 35 | return reflect.TypeOf(false) 36 | case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz: 37 | return reflect.TypeOf(time.Time{}) 38 | case oid.T_bytea: 39 | return reflect.TypeOf([]byte(nil)) 40 | default: 41 | return reflect.TypeOf(new(interface{})).Elem() 42 | } 43 | } 44 | 45 | func (fd fieldDesc) Name() string { 46 | return oid.TypeName[fd.OID] 47 | } 48 | 49 | func (fd fieldDesc) Length() (length int64, ok bool) { 50 | switch fd.OID { 51 | case oid.T_text, oid.T_bytea: 52 | return math.MaxInt64, true 53 | case oid.T_varchar, oid.T_bpchar: 54 | return int64(fd.Mod - headerSize), true 55 | default: 56 | return 0, false 57 | } 58 | } 59 | 60 | func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) { 61 | switch fd.OID { 62 | case oid.T_numeric, oid.T__numeric: 63 | mod := fd.Mod - headerSize 64 | precision = int64((mod >> 16) & 0xffff) 65 | scale = int64(mod & 0xffff) 66 | return precision, scale, true 67 | default: 68 | return 0, 0, false 69 | } 70 | } 71 | 72 | // ColumnTypeScanType returns the value type that can be used to scan types into. 73 | func (rs *rows) ColumnTypeScanType(index int) reflect.Type { 74 | return rs.colTyps[index].Type() 75 | } 76 | 77 | // ColumnTypeDatabaseTypeName return the database system type name. 78 | func (rs *rows) ColumnTypeDatabaseTypeName(index int) string { 79 | return rs.colTyps[index].Name() 80 | } 81 | 82 | // ColumnTypeLength returns the length of the column type if the column is a 83 | // variable length type. If the column is not a variable length type ok 84 | // should return false. 85 | func (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) { 86 | return rs.colTyps[index].Length() 87 | } 88 | 89 | // ColumnTypePrecisionScale should return the precision and scale for decimal 90 | // types. If not applicable, ok should be false. 91 | func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) { 92 | return rs.colTyps[index].PrecisionScale() 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "net" 8 | "os" 9 | "os/user" 10 | "path/filepath" 11 | ) 12 | 13 | // ssl generates a function to upgrade a net.Conn based on the "sslmode" and 14 | // related settings. The function is nil when no upgrade should take place. 15 | func ssl(o values) (func(net.Conn) (net.Conn, error), error) { 16 | verifyCaOnly := false 17 | tlsConf := tls.Config{} 18 | switch mode := o["sslmode"]; mode { 19 | // "require" is the default. 20 | case "", "require": 21 | // We must skip TLS's own verification since it requires full 22 | // verification since Go 1.3. 23 | tlsConf.InsecureSkipVerify = true 24 | 25 | // From http://www.postgresql.org/docs/current/static/libpq-ssl.html: 26 | // 27 | // Note: For backwards compatibility with earlier versions of 28 | // PostgreSQL, if a root CA file exists, the behavior of 29 | // sslmode=require will be the same as that of verify-ca, meaning the 30 | // server certificate is validated against the CA. Relying on this 31 | // behavior is discouraged, and applications that need certificate 32 | // validation should always use verify-ca or verify-full. 33 | if sslrootcert, ok := o["sslrootcert"]; ok { 34 | if _, err := os.Stat(sslrootcert); err == nil { 35 | verifyCaOnly = true 36 | } else { 37 | delete(o, "sslrootcert") 38 | } 39 | } 40 | case "verify-ca": 41 | // We must skip TLS's own verification since it requires full 42 | // verification since Go 1.3. 43 | tlsConf.InsecureSkipVerify = true 44 | verifyCaOnly = true 45 | case "verify-full": 46 | tlsConf.ServerName = o["host"] 47 | case "disable": 48 | return nil, nil 49 | default: 50 | return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) 51 | } 52 | 53 | err := sslClientCertificates(&tlsConf, o) 54 | if err != nil { 55 | return nil, err 56 | } 57 | err = sslCertificateAuthority(&tlsConf, o) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | // Accept renegotiation requests initiated by the backend. 63 | // 64 | // Renegotiation was deprecated then removed from PostgreSQL 9.5, but 65 | // the default configuration of older versions has it enabled. Redshift 66 | // also initiates renegotiations and cannot be reconfigured. 67 | tlsConf.Renegotiation = tls.RenegotiateFreelyAsClient 68 | 69 | return func(conn net.Conn) (net.Conn, error) { 70 | client := tls.Client(conn, &tlsConf) 71 | if verifyCaOnly { 72 | err := sslVerifyCertificateAuthority(client, &tlsConf) 73 | if err != nil { 74 | return nil, err 75 | } 76 | } 77 | return client, nil 78 | }, nil 79 | } 80 | 81 | // sslClientCertificates adds the certificate specified in the "sslcert" and 82 | // "sslkey" settings, or if they aren't set, from the .postgresql directory 83 | // in the user's home directory. The configured files must exist and have 84 | // the correct permissions. 85 | func sslClientCertificates(tlsConf *tls.Config, o values) error { 86 | // user.Current() might fail when cross-compiling. We have to ignore the 87 | // error and continue without home directory defaults, since we wouldn't 88 | // know from where to load them. 89 | user, _ := user.Current() 90 | 91 | // In libpq, the client certificate is only loaded if the setting is not blank. 92 | // 93 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1036-L1037 94 | sslcert := o["sslcert"] 95 | if len(sslcert) == 0 && user != nil { 96 | sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt") 97 | } 98 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045 99 | if len(sslcert) == 0 { 100 | return nil 101 | } 102 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054 103 | if _, err := os.Stat(sslcert); os.IsNotExist(err) { 104 | return nil 105 | } else if err != nil { 106 | return err 107 | } 108 | 109 | // In libpq, the ssl key is only loaded if the setting is not blank. 110 | // 111 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1123-L1222 112 | sslkey := o["sslkey"] 113 | if len(sslkey) == 0 && user != nil { 114 | sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key") 115 | } 116 | 117 | if len(sslkey) > 0 { 118 | if err := sslKeyPermissions(sslkey); err != nil { 119 | return err 120 | } 121 | } 122 | 123 | cert, err := tls.LoadX509KeyPair(sslcert, sslkey) 124 | if err != nil { 125 | return err 126 | } 127 | 128 | tlsConf.Certificates = []tls.Certificate{cert} 129 | return nil 130 | } 131 | 132 | // sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. 133 | func sslCertificateAuthority(tlsConf *tls.Config, o values) error { 134 | // In libpq, the root certificate is only loaded if the setting is not blank. 135 | // 136 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951 137 | if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 { 138 | tlsConf.RootCAs = x509.NewCertPool() 139 | 140 | cert, err := ioutil.ReadFile(sslrootcert) 141 | if err != nil { 142 | return err 143 | } 144 | 145 | if !tlsConf.RootCAs.AppendCertsFromPEM(cert) { 146 | return fmterrorf("couldn't parse pem in sslrootcert") 147 | } 148 | } 149 | 150 | return nil 151 | } 152 | 153 | // sslVerifyCertificateAuthority carries out a TLS handshake to the server and 154 | // verifies the presented certificate against the CA, i.e. the one specified in 155 | // sslrootcert or the system CA if sslrootcert was not specified. 156 | func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) error { 157 | err := client.Handshake() 158 | if err != nil { 159 | return err 160 | } 161 | certs := client.ConnectionState().PeerCertificates 162 | opts := x509.VerifyOptions{ 163 | DNSName: client.ConnectionState().ServerName, 164 | Intermediates: x509.NewCertPool(), 165 | Roots: tlsConf.RootCAs, 166 | } 167 | for i, cert := range certs { 168 | if i == 0 { 169 | continue 170 | } 171 | opts.Intermediates.AddCert(cert) 172 | } 173 | _, err = certs[0].Verify(opts) 174 | return err 175 | } 176 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_permissions.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package pq 4 | 5 | import "os" 6 | 7 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 8 | // The key file should have very little access. 9 | // 10 | // libpq does not check key file permissions on Windows. 11 | func sslKeyPermissions(sslkey string) error { 12 | info, err := os.Stat(sslkey) 13 | if err != nil { 14 | return err 15 | } 16 | if info.Mode().Perm()&0077 != 0 { 17 | return ErrSSLKeyHasWorldPermissions 18 | } 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pq 4 | 5 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 6 | // The key file should have very little access. 7 | // 8 | // libpq does not check key file permissions on Windows. 9 | func sslKeyPermissions(string) error { return nil } 10 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/url.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | nurl "net/url" 7 | "sort" 8 | "strings" 9 | ) 10 | 11 | // ParseURL no longer needs to be used by clients of this library since supplying a URL as a 12 | // connection string to sql.Open() is now supported: 13 | // 14 | // sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") 15 | // 16 | // It remains exported here for backwards-compatibility. 17 | // 18 | // ParseURL converts a url to a connection string for driver.Open. 19 | // Example: 20 | // 21 | // "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" 22 | // 23 | // converts to: 24 | // 25 | // "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" 26 | // 27 | // A minimal example: 28 | // 29 | // "postgres://" 30 | // 31 | // This will be blank, causing driver.Open to use all of the defaults 32 | func ParseURL(url string) (string, error) { 33 | u, err := nurl.Parse(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | if u.Scheme != "postgres" && u.Scheme != "postgresql" { 39 | return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) 40 | } 41 | 42 | var kvs []string 43 | escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) 44 | accrue := func(k, v string) { 45 | if v != "" { 46 | kvs = append(kvs, k+"="+escaper.Replace(v)) 47 | } 48 | } 49 | 50 | if u.User != nil { 51 | v := u.User.Username() 52 | accrue("user", v) 53 | 54 | v, _ = u.User.Password() 55 | accrue("password", v) 56 | } 57 | 58 | if host, port, err := net.SplitHostPort(u.Host); err != nil { 59 | accrue("host", u.Host) 60 | } else { 61 | accrue("host", host) 62 | accrue("port", port) 63 | } 64 | 65 | if u.Path != "" { 66 | accrue("dbname", u.Path[1:]) 67 | } 68 | 69 | q := u.Query() 70 | for k := range q { 71 | accrue(k, q.Get(k)) 72 | } 73 | 74 | sort.Strings(kvs) // Makes testing easier (not a performance concern) 75 | return strings.Join(kvs, " "), nil 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_posix.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | 3 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun 4 | 5 | package pq 6 | 7 | import ( 8 | "os" 9 | "os/user" 10 | ) 11 | 12 | func userCurrent() (string, error) { 13 | u, err := user.Current() 14 | if err == nil { 15 | return u.Username, nil 16 | } 17 | 18 | name := os.Getenv("USER") 19 | if name != "" { 20 | return name, nil 21 | } 22 | 23 | return "", ErrCouldNotDetectUsername 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_windows.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | package pq 3 | 4 | import ( 5 | "path/filepath" 6 | "syscall" 7 | ) 8 | 9 | // Perform Windows user name lookup identically to libpq. 10 | // 11 | // The PostgreSQL code makes use of the legacy Win32 function 12 | // GetUserName, and that function has not been imported into stock Go. 13 | // GetUserNameEx is available though, the difference being that a 14 | // wider range of names are available. To get the output to be the 15 | // same as GetUserName, only the base (or last) component of the 16 | // result is returned. 17 | func userCurrent() (string, error) { 18 | pw_name := make([]uint16, 128) 19 | pwname_size := uint32(len(pw_name)) - 1 20 | err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) 21 | if err != nil { 22 | return "", ErrCouldNotDetectUsername 23 | } 24 | s := syscall.UTF16ToString(pw_name) 25 | u := filepath.Base(s) 26 | return u, nil 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/uuid.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | ) 7 | 8 | // decodeUUIDBinary interprets the binary format of a uuid, returning it in text format. 9 | func decodeUUIDBinary(src []byte) ([]byte, error) { 10 | if len(src) != 16 { 11 | return nil, fmt.Errorf("pq: unable to decode uuid; bad length: %d", len(src)) 12 | } 13 | 14 | dst := make([]byte, 36) 15 | dst[8], dst[13], dst[18], dst[23] = '-', '-', '-', '-' 16 | hex.Encode(dst[0:], src[0:4]) 17 | hex.Encode(dst[9:], src[4:6]) 18 | hex.Encode(dst[14:], src[6:8]) 19 | hex.Encode(dst[19:], src[8:10]) 20 | hex.Encode(dst[24:], src[10:16]) 21 | 22 | return dst, nil 23 | } 24 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at https://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at https://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/bcrypt/base64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bcrypt 6 | 7 | import "encoding/base64" 8 | 9 | const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 10 | 11 | var bcEncoding = base64.NewEncoding(alphabet) 12 | 13 | func base64Encode(src []byte) []byte { 14 | n := bcEncoding.EncodedLen(len(src)) 15 | dst := make([]byte, n) 16 | bcEncoding.Encode(dst, src) 17 | for dst[n-1] == '=' { 18 | n-- 19 | } 20 | return dst[:n] 21 | } 22 | 23 | func base64Decode(src []byte) ([]byte, error) { 24 | numOfEquals := 4 - (len(src) % 4) 25 | for i := 0; i < numOfEquals; i++ { 26 | src = append(src, '=') 27 | } 28 | 29 | dst := make([]byte, bcEncoding.DecodedLen(len(src))) 30 | n, err := bcEncoding.Decode(dst, src) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return dst[:n], nil 35 | } 36 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/blowfish/block.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package blowfish 6 | 7 | // getNextWord returns the next big-endian uint32 value from the byte slice 8 | // at the given position in a circular manner, updating the position. 9 | func getNextWord(b []byte, pos *int) uint32 { 10 | var w uint32 11 | j := *pos 12 | for i := 0; i < 4; i++ { 13 | w = w<<8 | uint32(b[j]) 14 | j++ 15 | if j >= len(b) { 16 | j = 0 17 | } 18 | } 19 | *pos = j 20 | return w 21 | } 22 | 23 | // ExpandKey performs a key expansion on the given *Cipher. Specifically, it 24 | // performs the Blowfish algorithm's key schedule which sets up the *Cipher's 25 | // pi and substitution tables for calls to Encrypt. This is used, primarily, 26 | // by the bcrypt package to reuse the Blowfish key schedule during its 27 | // set up. It's unlikely that you need to use this directly. 28 | func ExpandKey(key []byte, c *Cipher) { 29 | j := 0 30 | for i := 0; i < 18; i++ { 31 | // Using inlined getNextWord for performance. 32 | var d uint32 33 | for k := 0; k < 4; k++ { 34 | d = d<<8 | uint32(key[j]) 35 | j++ 36 | if j >= len(key) { 37 | j = 0 38 | } 39 | } 40 | c.p[i] ^= d 41 | } 42 | 43 | var l, r uint32 44 | for i := 0; i < 18; i += 2 { 45 | l, r = encryptBlock(l, r, c) 46 | c.p[i], c.p[i+1] = l, r 47 | } 48 | 49 | for i := 0; i < 256; i += 2 { 50 | l, r = encryptBlock(l, r, c) 51 | c.s0[i], c.s0[i+1] = l, r 52 | } 53 | for i := 0; i < 256; i += 2 { 54 | l, r = encryptBlock(l, r, c) 55 | c.s1[i], c.s1[i+1] = l, r 56 | } 57 | for i := 0; i < 256; i += 2 { 58 | l, r = encryptBlock(l, r, c) 59 | c.s2[i], c.s2[i+1] = l, r 60 | } 61 | for i := 0; i < 256; i += 2 { 62 | l, r = encryptBlock(l, r, c) 63 | c.s3[i], c.s3[i+1] = l, r 64 | } 65 | } 66 | 67 | // This is similar to ExpandKey, but folds the salt during the key 68 | // schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero 69 | // salt passed in, reusing ExpandKey turns out to be a place of inefficiency 70 | // and specializing it here is useful. 71 | func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { 72 | j := 0 73 | for i := 0; i < 18; i++ { 74 | c.p[i] ^= getNextWord(key, &j) 75 | } 76 | 77 | j = 0 78 | var l, r uint32 79 | for i := 0; i < 18; i += 2 { 80 | l ^= getNextWord(salt, &j) 81 | r ^= getNextWord(salt, &j) 82 | l, r = encryptBlock(l, r, c) 83 | c.p[i], c.p[i+1] = l, r 84 | } 85 | 86 | for i := 0; i < 256; i += 2 { 87 | l ^= getNextWord(salt, &j) 88 | r ^= getNextWord(salt, &j) 89 | l, r = encryptBlock(l, r, c) 90 | c.s0[i], c.s0[i+1] = l, r 91 | } 92 | 93 | for i := 0; i < 256; i += 2 { 94 | l ^= getNextWord(salt, &j) 95 | r ^= getNextWord(salt, &j) 96 | l, r = encryptBlock(l, r, c) 97 | c.s1[i], c.s1[i+1] = l, r 98 | } 99 | 100 | for i := 0; i < 256; i += 2 { 101 | l ^= getNextWord(salt, &j) 102 | r ^= getNextWord(salt, &j) 103 | l, r = encryptBlock(l, r, c) 104 | c.s2[i], c.s2[i+1] = l, r 105 | } 106 | 107 | for i := 0; i < 256; i += 2 { 108 | l ^= getNextWord(salt, &j) 109 | r ^= getNextWord(salt, &j) 110 | l, r = encryptBlock(l, r, c) 111 | c.s3[i], c.s3[i+1] = l, r 112 | } 113 | } 114 | 115 | func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { 116 | xl, xr := l, r 117 | xl ^= c.p[0] 118 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] 119 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] 120 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] 121 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] 122 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] 123 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] 124 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] 125 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] 126 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] 127 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] 128 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] 129 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] 130 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] 131 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] 132 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] 133 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] 134 | xr ^= c.p[17] 135 | return xr, xl 136 | } 137 | 138 | func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { 139 | xl, xr := l, r 140 | xl ^= c.p[17] 141 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] 142 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] 143 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] 144 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] 145 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] 146 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] 147 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] 148 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] 149 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] 150 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] 151 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] 152 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] 153 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] 154 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] 155 | xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] 156 | xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] 157 | xr ^= c.p[0] 158 | return xr, xl 159 | } 160 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/blowfish/cipher.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. 6 | // 7 | // Blowfish is a legacy cipher and its short block size makes it vulnerable to 8 | // birthday bound attacks (see https://sweet32.info). It should only be used 9 | // where compatibility with legacy systems, not security, is the goal. 10 | // 11 | // Deprecated: any new system should use AES (from crypto/aes, if necessary in 12 | // an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from 13 | // golang.org/x/crypto/chacha20poly1305). 14 | package blowfish // import "golang.org/x/crypto/blowfish" 15 | 16 | // The code is a port of Bruce Schneier's C implementation. 17 | // See https://www.schneier.com/blowfish.html. 18 | 19 | import "strconv" 20 | 21 | // The Blowfish block size in bytes. 22 | const BlockSize = 8 23 | 24 | // A Cipher is an instance of Blowfish encryption using a particular key. 25 | type Cipher struct { 26 | p [18]uint32 27 | s0, s1, s2, s3 [256]uint32 28 | } 29 | 30 | type KeySizeError int 31 | 32 | func (k KeySizeError) Error() string { 33 | return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) 34 | } 35 | 36 | // NewCipher creates and returns a Cipher. 37 | // The key argument should be the Blowfish key, from 1 to 56 bytes. 38 | func NewCipher(key []byte) (*Cipher, error) { 39 | var result Cipher 40 | if k := len(key); k < 1 || k > 56 { 41 | return nil, KeySizeError(k) 42 | } 43 | initCipher(&result) 44 | ExpandKey(key, &result) 45 | return &result, nil 46 | } 47 | 48 | // NewSaltedCipher creates a returns a Cipher that folds a salt into its key 49 | // schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is 50 | // sufficient and desirable. For bcrypt compatibility, the key can be over 56 51 | // bytes. 52 | func NewSaltedCipher(key, salt []byte) (*Cipher, error) { 53 | if len(salt) == 0 { 54 | return NewCipher(key) 55 | } 56 | var result Cipher 57 | if k := len(key); k < 1 { 58 | return nil, KeySizeError(k) 59 | } 60 | initCipher(&result) 61 | expandKeyWithSalt(key, salt, &result) 62 | return &result, nil 63 | } 64 | 65 | // BlockSize returns the Blowfish block size, 8 bytes. 66 | // It is necessary to satisfy the Block interface in the 67 | // package "crypto/cipher". 68 | func (c *Cipher) BlockSize() int { return BlockSize } 69 | 70 | // Encrypt encrypts the 8-byte buffer src using the key k 71 | // and stores the result in dst. 72 | // Note that for amounts of data larger than a block, 73 | // it is not safe to just call Encrypt on successive blocks; 74 | // instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). 75 | func (c *Cipher) Encrypt(dst, src []byte) { 76 | l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) 77 | r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) 78 | l, r = encryptBlock(l, r, c) 79 | dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) 80 | dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) 81 | } 82 | 83 | // Decrypt decrypts the 8-byte buffer src using the key k 84 | // and stores the result in dst. 85 | func (c *Cipher) Decrypt(dst, src []byte) { 86 | l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) 87 | r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) 88 | l, r = decryptBlock(l, r, c) 89 | dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) 90 | dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) 91 | } 92 | 93 | func initCipher(c *Cipher) { 94 | copy(c.p[0:], p[0:]) 95 | copy(c.s0[0:], s0[0:]) 96 | copy(c.s1[0:], s1[0:]) 97 | copy(c.s2[0:], s2[0:]) 98 | copy(c.s3[0:], s3[0:]) 99 | } 100 | --------------------------------------------------------------------------------