dndex/server/auth/generate.go

101 lines
2.2 KiB
Go

package auth
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"local/dndex/storage"
"local/dndex/storage/entity"
"net/http"
"github.com/google/uuid"
"gopkg.in/mgo.v2/bson"
)
func GeneratePlain(g storage.RateLimitedGraph, r *http.Request) (string, error) {
token, _, err := generateToken(g, r)
if err != nil {
return "", err
}
return token.Obfuscate()
}
func Generate(g storage.RateLimitedGraph, r *http.Request, salt string) (string, error) {
token, key, err := generateToken(g, r)
if err != nil {
return "", err
}
return token.Encode(salt + key)
}
func generateToken(g storage.RateLimitedGraph, r *http.Request) (Token, string, error) {
namespaceRequested := readRequestedNamespace(r)
if namespaceRequested == "" {
return Token{}, "", errors.New("no namespace found")
}
key, err := getKeyForNamespace(r.Context(), g, namespaceRequested)
if err != nil {
return Token{}, "", err
}
token, err := makeTokenForNamespace(r.Context(), g, namespaceRequested)
if err != nil {
return Token{}, "", err
}
return token, key, nil
}
func readRequestedNamespace(r *http.Request) string {
return readRequested(r, UserKey)
}
func readRequested(r *http.Request, key string) string {
switch r.Header.Get("Content-Type") {
case "application/json":
b, _ := ioutil.ReadAll(r.Body)
r.Body = struct {
io.Reader
io.Closer
}{
Reader: bytes.NewReader(b),
Closer: r.Body,
}
m := bson.M{}
json.Unmarshal(b, &m)
v, ok := m[key]
if !ok {
return ""
}
return fmt.Sprint(v)
default:
return r.FormValue(key)
}
}
func getKeyForNamespace(ctx context.Context, g storage.RateLimitedGraph, namespace string) (string, error) {
namespaceOne, err := g.Get(ctx, toAuthNamespace(namespace), UserKey)
if err != nil {
return "", err
}
return namespaceOne.Title, nil
}
func makeTokenForNamespace(ctx context.Context, g storage.RateLimitedGraph, namespace string) (Token, error) {
token := Token{
Namespace: namespace,
ID: uuid.New().String(),
}
obf, err := token.Obfuscate()
if err != nil {
return Token{}, err
}
one := entity.One{
ID: token.ID,
Title: obf,
}
return token, g.Insert(ctx, toAuthNamespace(namespace), one)
}