You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-login/login/gogs/handler.go

117 lines
2.4 KiB
Go

// Copyright 2017 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gogs
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"git.awesome-for.me/liuzhiguo/go-login/login"
)
type token struct {
Name string `json:"name"`
Sha1 string `json:"sha1,omitempty"`
}
type handler struct {
next http.Handler
label string
login string
server string
client *http.Client
}
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := r.FormValue("username")
pass := r.FormValue("password")
if (user == "" || pass == "") && h.login != "" {
http.Redirect(w, r, h.login, 303)
return
}
token, err := h.createFindToken(user, pass)
if err != nil {
ctx = login.WithError(ctx, err)
} else {
ctx = login.WithToken(ctx, &login.Token{
Access: token.Sha1,
})
}
h.next.ServeHTTP(w, r.WithContext(ctx))
}
func (h *handler) createFindToken(user, pass string) (*token, error) {
tokens, err := h.findTokens(user, pass)
if err != nil {
return nil, err
}
for _, token := range tokens {
if token.Name == h.label {
return token, nil
}
}
return h.createToken(user, pass)
}
func (h *handler) createToken(user, pass string) (*token, error) {
path := fmt.Sprintf("%s/api/v1/users/%s/tokens", h.server, user)
buf := new(bytes.Buffer)
json.NewEncoder(buf).Encode(&token{
Name: h.label,
})
req, err := http.NewRequest("POST", path, buf)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(user, pass)
res, err := h.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode > 299 {
return nil, errors.New(
http.StatusText(res.StatusCode),
)
}
out := new(token)
err = json.NewDecoder(res.Body).Decode(out)
return out, err
}
func (h *handler) findTokens(user, pass string) ([]*token, error) {
path := fmt.Sprintf("%s/api/v1/users/%s/tokens", h.server, user)
req, err := http.NewRequest("GET", path, nil)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(user, pass)
res, err := h.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode > 299 {
return nil, errors.New(
http.StatusText(res.StatusCode),
)
}
out := []*token{}
err = json.NewDecoder(res.Body).Decode(&out)
return out, err
}