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) }