123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- // Copyright 2019 The Gogs Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
- package srcgraph
- import (
- "net/http"
- "time"
- "github.com/Unknwon/com"
- adapter "github.com/sourcegraph/external-service-adapter"
- log "gopkg.in/clog.v1"
- "github.com/gogs/gogs/models"
- "github.com/gogs/gogs/models/errors"
- "github.com/gogs/gogs/pkg/setting"
- )
- func NewHandler() http.HandlerFunc {
- h := adapter.NewHandler(externalServicer{}, adapter.Options{
- URL: setting.AppURL,
- PathPrefix: "/-/srcgraph",
- MaxPageLen: 100000, // Current version returns all repositories at once, does not matter
- })
- return h.ServeHTTP
- }
- type externalServicer struct{}
- func (es externalServicer) ListRepos(ai adapter.AuthInfo, params adapter.Params) ([]*adapter.Repo, adapter.Page, error) {
- return es.listUserRepos("", ai, params)
- }
- func (es externalServicer) ListUserRepos(user string, ai adapter.AuthInfo, params adapter.Params) ([]*adapter.Repo, adapter.Page, error) {
- return es.listUserRepos(user, ai, params)
- }
- func toRepo(r *models.Repository) *adapter.Repo {
- var parent *adapter.Repo
- if r.IsFork {
- parent = toRepo(r.BaseRepo)
- }
- cl := r.CloneLink()
- return &adapter.Repo{
- ID: com.ToStr(r.ID),
- Name: r.Name,
- Slug: r.Name,
- FullName: r.FullName(),
- SCM: "git",
- Description: r.Description,
- IsPrivate: r.IsPrivate,
- Parent: parent,
- Links: []adapter.Link{
- {adapter.CloneSSH, cl.SSH},
- {adapter.CloneHTTP, cl.HTTPS},
- },
- }
- }
- func (es externalServicer) listUserRepos(username string, ai adapter.AuthInfo, params adapter.Params) ([]*adapter.Repo, adapter.Page, error) {
- authUser, err := userFromAuthInfo(ai)
- if err != nil {
- if errors.IsUserNotExist(err) {
- return nil, adapter.Page{}, errors.New("403 Forbidden")
- }
- log.Error(2, "Failed to get user from auth info: %v", err)
- return nil, adapter.Page{}, errors.New("500 Internal Server Error")
- }
- // Fall back to authenticated user
- if username == "" {
- username = authUser.Name
- }
- user, err := models.GetUserByName(username)
- if err != nil {
- if errors.IsUserNotExist(err) {
- return nil, adapter.Page{}, errors.New("404 Not Found")
- }
- log.Error(2, "Failed to get user by username %q: %v", username, err)
- return nil, adapter.Page{}, errors.New("500 Internal Server Error")
- }
- // Only list public repositories if user requests someone else's repository list,
- // or an organization isn't a member of.
- var ownRepos []*models.Repository
- if user.IsOrganization() {
- ownRepos, _, err = user.GetUserRepositories(authUser.ID, params.Page, user.NumRepos)
- } else {
- ownRepos, err = models.GetUserRepositories(&models.UserRepoOptions{
- UserID: user.ID,
- Private: authUser.ID == user.ID,
- Page: params.Page,
- PageSize: user.NumRepos,
- })
- }
- if err != nil {
- log.Error(2, "Failed to get repositories of user %q: %v", username, err)
- return nil, adapter.Page{}, errors.New("500 Internal Server Error")
- }
- if err = models.RepositoryList(ownRepos).LoadAttributes(); err != nil {
- log.Error(2, "Failed to load attributes of repositories: %v", err)
- return nil, adapter.Page{}, errors.New("500 Internal Server Error")
- }
- // Early return for querying other user's repositories
- if authUser.ID != user.ID {
- repos := make([]*adapter.Repo, len(ownRepos))
- for i := range ownRepos {
- repos[i] = toRepo(ownRepos[i])
- }
- return repos, adapter.Page{Last: 1}, nil
- }
- accessibleRepos, err := user.GetRepositoryAccesses()
- if err != nil {
- log.Error(2, "Failed to get accessible repositories of user %q: %v", username, err)
- return nil, adapter.Page{}, errors.New("500 Internal Server Error")
- }
- numOwnRepos := len(ownRepos)
- repos := make([]*adapter.Repo, numOwnRepos+len(accessibleRepos))
- for i := range ownRepos {
- repos[i] = toRepo(ownRepos[i])
- }
- i := numOwnRepos
- for repo := range accessibleRepos {
- repos[i] = toRepo(repo)
- i++
- }
- return repos, adapter.Page{Last: 1}, nil
- }
- func userFromAuthInfo(ai adapter.AuthInfo) (*models.User, error) {
- if ai.Method == adapter.AuthBasic {
- u, err := models.UserLogin(ai.Username, ai.Password, -1)
- if err != nil {
- return nil, err
- }
- if u.IsEnabledTwoFactor() {
- return nil, errors.New(
- "User with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password." +
- " Please create and use personal access token on user settings page.")
- }
- return u, nil
- }
- t, err := models.GetAccessTokenBySHA(ai.Token)
- if err != nil {
- if models.IsErrAccessTokenEmpty(err) || models.IsErrAccessTokenNotExist(err) {
- return nil, errors.UserNotExist{}
- }
- return nil, err
- }
- t.Updated = time.Now()
- u, err := models.GetUserByID(t.UID)
- if err != nil {
- return nil, err
- }
- return u, models.UpdateAccessToken(t)
- }
|