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.
117 lines
2.4 KiB
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
|
|
}
|