gistea/router/session/session.go

127 lines
2.4 KiB
Go

package session
import (
"encoding/gob"
"errors"
"fmt"
"net/http"
"code.gitea.io/sdk/gitea"
"github.com/gorilla/sessions"
"github.com/markbates/goth/gothic"
)
const (
sessionCookie = "_gistea_session"
infoKey = "_gistea_info"
)
type Store struct {
Store sessions.Store
GiteaURL string
}
type Info struct {
Org string
Token string
}
func init() {
gob.Register(&Info{})
}
func (s *Store) RequireAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sess, err := s.Store.Get(r, sessionCookie)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if _, ok := sess.Values[infoKey]; !ok {
gothic.BeginAuthHandler(w, r)
return
}
next.ServeHTTP(w, r)
})
}
func (s *Store) Info(r *http.Request) (*Info, error) {
sess, err := s.Store.Get(r, sessionCookie)
if err != nil {
return nil, err
}
if infoAny, ok := sess.Values[infoKey]; ok {
if info, ok := infoAny.(*Info); ok {
return info, nil
}
}
return nil, errors.New("could not get session info")
}
func (s *Store) HasAuth(r *http.Request) bool {
i, _ := s.Info(r)
return i != nil
}
func (s *Store) CompleteAuth(w http.ResponseWriter, r *http.Request, token string) error {
client, err := gitea.NewClient(s.GiteaURL, gitea.SetToken(token))
if err != nil {
return err
}
profile, _, err := client.GetMyUserInfo()
if err != nil {
return err
}
org := fmt.Sprintf("%s-gists", profile.UserName)
_, resp, err := client.GetOrg(org)
if err != nil {
if resp != nil && resp.StatusCode == http.StatusNotFound {
if _, _, err := client.CreateOrg(gitea.CreateOrgOption{
Name: org,
Visibility: gitea.VisibleTypePublic,
}); err != nil {
return err
}
} else {
return err
}
}
sess, err := s.Store.New(r, sessionCookie)
if err != nil {
return err
}
sess.Values[infoKey] = &Info{
Org: org,
Token: token,
}
return s.Store.Save(r, w, sess)
}
func (s *Store) Repos(r *http.Request) ([]*gitea.Repository, error) {
info, err := s.Info(r)
if err != nil {
return nil, err
}
client, err := gitea.NewClient(s.GiteaURL, gitea.SetToken(info.Token))
if err != nil {
return nil, err
}
repos, _, err := client.ListOrgRepos(info.Org, gitea.ListOrgReposOptions{})
return repos, err
}
func NewStore(sessionSecret, giteURL string) *Store {
store := sessions.NewCookieStore([]byte(sessionSecret))
return &Store{
Store: store,
GiteaURL: giteURL,
}
}