token management is ok with middleware .. OK
This commit is contained in:
parent
ba8d73aa8c
commit
0962196e00
|
@ -1,7 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.xdrm.io/example/aicra/controller/db"
|
"git.xdrm.io/example/aicra/db"
|
||||||
e "git.xdrm.io/go/aicra/err"
|
e "git.xdrm.io/go/aicra/err"
|
||||||
i "git.xdrm.io/go/aicra/implement"
|
i "git.xdrm.io/go/aicra/implement"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ func Get(d i.Arguments, r *i.Response) i.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) Check if match for this key */
|
/* (3) Check if match for this key */
|
||||||
val := cli.Get(key)
|
val := cli.Get(db.DATA, key)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
r.Err = e.NoMatchFound
|
r.Err = e.NoMatchFound
|
||||||
return *r
|
return *r
|
||||||
|
@ -57,13 +57,13 @@ func Post(d i.Arguments, r *i.Response) i.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) Check if key already used */
|
/* (3) Check if key already used */
|
||||||
if cli.Get(url) != nil {
|
if cli.Get(db.DATA, url) != nil {
|
||||||
r.Err = e.AlreadyExists
|
r.Err = e.AlreadyExists
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) Store */
|
/* (4) Store */
|
||||||
if !cli.Set(url, target) {
|
if !cli.Set(db.DATA, url, target) {
|
||||||
r.Err = e.Failure
|
r.Err = e.Failure
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
|
@ -92,13 +92,13 @@ func Put(d i.Arguments, r *i.Response) i.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) Check if key already used */
|
/* (3) Check if key already used */
|
||||||
if cli.Get(url) == nil {
|
if cli.Get(db.DATA, url) == nil {
|
||||||
r.Err = e.NoMatchFound
|
r.Err = e.NoMatchFound
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) Update */
|
/* (4) Update */
|
||||||
if !cli.Set(url, target) {
|
if !cli.Set(db.DATA, url, target) {
|
||||||
r.Err = e.Failure
|
r.Err = e.Failure
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
|
@ -126,13 +126,13 @@ func Delete(d i.Arguments, r *i.Response) i.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (3) Check if key already used */
|
/* (3) Check if key already used */
|
||||||
if cli.Get(url) == nil {
|
if cli.Get(db.DATA, url) == nil {
|
||||||
r.Err = e.NoMatchFound
|
r.Err = e.NoMatchFound
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (4) Delete */
|
/* (4) Delete */
|
||||||
if !cli.Del(url) {
|
if !cli.Del(db.DATA, url) {
|
||||||
r.Err = e.Failure
|
r.Err = e.Failure
|
||||||
return *r
|
return *r
|
||||||
}
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
e "git.xdrm.io/go/aicra/err"
|
|
||||||
i "git.xdrm.io/go/aicra/implement"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Builds an access token from credentials
|
|
||||||
func Post(d i.Arguments, r *i.Response) i.Response {
|
|
||||||
|
|
||||||
if d.Has("_AUTHORIZATION_") {
|
|
||||||
fmt.Printf("authorization: '%s'\n", d["_AUTHORIZATION_"].(string))
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Err = e.Success
|
|
||||||
return *r
|
|
||||||
}
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding/hex"
|
||||||
|
"git.xdrm.io/example/aicra/db"
|
||||||
|
e "git.xdrm.io/go/aicra/err"
|
||||||
|
i "git.xdrm.io/go/aicra/implement"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Builds an access token from credentials
|
||||||
|
func Post(d i.Arguments, r *i.Response) i.Response {
|
||||||
|
|
||||||
|
/* (1) Init redis connection */
|
||||||
|
cli := db.Connect()
|
||||||
|
if cli == nil {
|
||||||
|
r.Err = e.Failure
|
||||||
|
return *r
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Extract api input */
|
||||||
|
role, ok := d["role"].(string)
|
||||||
|
if !ok {
|
||||||
|
r.Err = e.InvalidParam
|
||||||
|
r.Err.BindArgument("url")
|
||||||
|
return *r
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Generate token */
|
||||||
|
hasher := sha512.New()
|
||||||
|
defer hasher.Reset()
|
||||||
|
hasher.Write([]byte(strconv.FormatInt(time.Now().Unix(), 5)))
|
||||||
|
token := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
|
/* (4) Store */
|
||||||
|
if !cli.Set(db.TOKEN, token, role, time.Minute) {
|
||||||
|
r.Err = e.Failure
|
||||||
|
return *r
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Set("token", token)
|
||||||
|
r.Err = e.Success
|
||||||
|
return *r
|
||||||
|
}
|
|
@ -3,16 +3,23 @@ package db
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-redis/redis"
|
"github.com/go-redis/redis"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const NONCE = "go-tiny-url"
|
const NONCE = "go-tiny-url"
|
||||||
|
|
||||||
var domain = "data"
|
type Domain string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DATA Domain = "data"
|
||||||
|
TOKEN Domain = "token"
|
||||||
|
)
|
||||||
|
|
||||||
type db redis.Client
|
type db redis.Client
|
||||||
|
|
||||||
// Returns a connected client to dataset
|
// Returns a connected client to dataset
|
||||||
func Connect() *db {
|
func Connect() *db {
|
||||||
|
|
||||||
cli := redis.NewClient(&redis.Options{
|
cli := redis.NewClient(&redis.Options{
|
||||||
Addr: "127.0.0.1:6379",
|
Addr: "127.0.0.1:6379",
|
||||||
Password: "",
|
Password: "",
|
||||||
|
@ -27,10 +34,10 @@ func Connect() *db {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns value from key (nil if nothing)
|
// returns value from key (nil if nothing)
|
||||||
func (c *db) Get(key string) []byte {
|
func (c *db) Get(dom Domain, key string) []byte {
|
||||||
|
|
||||||
// 1. Try to get
|
// 1. Try to get
|
||||||
if val, err := (*redis.Client)(c).Get(fmt.Sprintf("%s:%s:%s", NONCE, domain, key)).Result(); err != nil {
|
if val, err := (*redis.Client)(c).Get(fmt.Sprintf("%s:%s:%s", NONCE, dom, key)).Result(); err != nil {
|
||||||
// 2. nil if nothing found
|
// 2. nil if nothing found
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -41,10 +48,15 @@ func (c *db) Get(key string) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// stores a value for a key (success state in return)
|
// stores a value for a key (success state in return)
|
||||||
func (c *db) Set(key string, value string) bool {
|
func (c *db) Set(dom Domain, key string, value string, exp ...time.Duration) bool {
|
||||||
|
|
||||||
|
var expiration time.Duration = 0
|
||||||
|
if len(exp) > 0 {
|
||||||
|
expiration = exp[0]
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Try to set
|
// 1. Try to set
|
||||||
if (*redis.Client)(c).Set(fmt.Sprintf("%s:%s:%s", NONCE, domain, key), value, 0).Err() != nil {
|
if (*redis.Client)(c).Set(fmt.Sprintf("%s:%s:%s", NONCE, dom, key), value, expiration).Err() != nil {
|
||||||
// 2. failure
|
// 2. failure
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -55,10 +67,10 @@ func (c *db) Set(key string, value string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// deletes the value for a key (success state in return)
|
// deletes the value for a key (success state in return)
|
||||||
func (c *db) Del(key string) bool {
|
func (c *db) Del(dom Domain, key string) bool {
|
||||||
|
|
||||||
// 1. Try to set
|
// 1. Try to set
|
||||||
if (*redis.Client)(c).Del(fmt.Sprintf("%s:%s:%s", NONCE, domain, key)).Err() != nil {
|
if (*redis.Client)(c).Del(fmt.Sprintf("%s:%s:%s", NONCE, dom, key)).Err() != nil {
|
||||||
// 2. failure
|
// 2. failure
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -67,9 +79,3 @@ func (c *db) Del(key string) bool {
|
||||||
return true
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch following operations to DATA dataset
|
|
||||||
func (c *db) SwitchData() { domain = "data" }
|
|
||||||
|
|
||||||
// Switch following operations to AUTH dataset
|
|
||||||
func (c *db) SwitchAuth() { domain = "auth" }
|
|
2
main.go
2
main.go
|
@ -1,4 +1,4 @@
|
||||||
package aicraserver
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.xdrm.io/go/aicra"
|
"git.xdrm.io/go/aicra"
|
||||||
|
|
|
@ -38,16 +38,15 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"/": {
|
"/": {
|
||||||
"auth": {
|
"token": {
|
||||||
"POST": {
|
"POST": {
|
||||||
"info": "returns a 1-minute access token",
|
"info": "creates a 1-minute access token",
|
||||||
"scope": [[]],
|
"scope": [[]],
|
||||||
"in": {
|
"in": {
|
||||||
"username": { "info": "user name", "type": "varchar(3,20)" },
|
"URL#0": { "info": "wanted role", "type": "varchar(3,10)", "name": "role" }
|
||||||
"password": { "info": "password", "type": "varchar(5,150)" }
|
|
||||||
},
|
},
|
||||||
"out": {
|
"out": {
|
||||||
"token": { "info": "access token", "type": "varchar(256,256)" }
|
"token": { "info": "access token", "type": "varchar(128,128)" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,41 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.xdrm.io/example/aicra/db"
|
||||||
"git.xdrm.io/go/aicra/middleware"
|
"git.xdrm.io/go/aicra/middleware"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Authentication middleware
|
// Authentication middleware
|
||||||
func Inspect(req http.Request, scope *middleware.Scope) {
|
func Inspect(req http.Request, scope *middleware.Scope) {
|
||||||
*scope = append(*scope, "admin")
|
|
||||||
|
// 1. get authorization header
|
||||||
|
token := req.Header.Get("Authorization")
|
||||||
|
|
||||||
|
// fail if no header
|
||||||
|
if len(token) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. fail on invalid token format
|
||||||
|
if len(token) != 128 || strings.ContainsAny(token, "$-_") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. get role for this token
|
||||||
|
cli := db.Connect()
|
||||||
|
if cli == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
role := cli.Get(db.TOKEN, token)
|
||||||
|
if role == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// add role to scope
|
||||||
|
*scope = append(*scope, string(role))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue