Skip to content

Commit

Permalink
add 403, add logs (#19)
Browse files Browse the repository at this point in the history
* add 403, add logs

* add fork err msg, add query url

* update docs
  • Loading branch information
wj00037 authored Oct 29, 2024
1 parent c7ed8dd commit 1c7ec28
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 31 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ v2.12.0](https://github.com/git-lfs/git-lfs/tree/v2.12.0/docs/api) server.
5. ~~认证时校验用户在仓库内权限。~~
6. 支持ssh。
7. ~~仓库添加github action。~~
8. 添加日志。
8. ~~添加日志。~~
9. 支持cdn。
16 changes: 13 additions & 3 deletions auth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"io"
"net/http"
"strings"

"github.com/sirupsen/logrus"
)

type Client struct {
Expand All @@ -19,19 +21,27 @@ func getParsedResponse(method, path string, header http.Header, body io.Reader,
panic(err)
}
req.Header = header
fmt.Println(strings.Split(path, "?")[0])
response, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer response.Body.Close()

if splitPath := strings.Split(path, "?"); len(splitPath) != 1 {
logrus.Infof("query %s with token | %d", splitPath[0], response.StatusCode)
} else {
logrus.Infof("query %s without token | %d", splitPath[0], response.StatusCode)
}

if response.StatusCode/100 != 2 {
if response.StatusCode == http.StatusNotFound {
return errors.New("repository not found")
return errors.New("not_found")
} else if response.StatusCode == http.StatusUnauthorized {
return errors.New("unauthorized")
} else if response.StatusCode == http.StatusForbidden {
return errors.New("forbidden")
}
return errors.New("error occurred accessing gitee")
return fmt.Errorf("system_error: %v", response.StatusCode)
}
data, err := io.ReadAll(response.Body)
if err != nil {
Expand Down
37 changes: 25 additions & 12 deletions auth/gitee.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/metalogical/BigFiles/config"
"github.com/sirupsen/logrus"
)

var (
Expand All @@ -23,7 +24,6 @@ var (
)

type giteeUser struct {
Login string `json:"login"`
Permission string `json:"permission"`
}

Expand Down Expand Up @@ -101,7 +101,8 @@ func CheckRepoOwner(userInRepo UserInRepo) error {
repo := new(Repo)
err := getParsedResponse("GET", path, headers, nil, &repo)
if err != nil {
return err
msg := err.Error() + ": check repo_id failed"
return errors.New(msg)
}
for _, allowedRepo := range allowedRepos {
if strings.Split(repo.Fullname, "/")[0] == allowedRepo {
Expand All @@ -116,8 +117,9 @@ func CheckRepoOwner(userInRepo UserInRepo) error {
}
}
}

return errors.New("your repository does not appear to have permission to use this lfs service")
msg := "forbidden: repo has no permission to use this lfs server"
logrus.Error(fmt.Sprintf("CheckRepoOwner | %s", msg))
return errors.New(msg)
}

// getToken gets access_token by username and password
Expand All @@ -135,7 +137,8 @@ func getToken(username, password string) (string, error) {
accessToken := new(AccessToken)
err := getParsedResponse("POST", path, headers, strings.NewReader(form.Encode()), &accessToken)
if err != nil {
return "", err
msg := err.Error() + ": get token failed. Or may be it is already a token"
return "", errors.New(msg)
}

return accessToken.Token, nil
Expand All @@ -156,27 +159,37 @@ func verifyUser(userInRepo UserInRepo) error {
giteeUser := new(giteeUser)
err := getParsedResponse("GET", path, headers, nil, &giteeUser)
if err != nil {
return err
msg := err.Error() + ": verify user permission failed"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg)
}

if giteeUser.Login != userInRepo.Username {
return errors.New("username does not match")
}
if userInRepo.Operation == "upload" {
for _, v := range uploadPermissions {
if giteeUser.Permission == v {
return nil
}
}
return errors.New("user has no permission uploading to the repository")
msg := fmt.Sprintf("forbidden: user %s has no permission to upload to %s/%s",
userInRepo.Username, userInRepo.Owner, userInRepo.Repo)
remindMsg := " \n如果您正在向fork仓库上传大文件,请确认您已使用如下命令修改了本地仓库的配置:" +
"\n`git config --local lfs.url https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}`" +
",\n其中{owner}/{repo}请改为您fork之后的仓库的名称。" +
"详阅:https://github.com/opensourceways/BigFiles/blob/master/docs/QuickStart.md"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg + remindMsg)
} else if userInRepo.Operation == "download" {
for _, v := range downloadPermissions {
if giteeUser.Permission == v {
return nil
}
}
return errors.New("user has no permission downloading in the repository")
msg := fmt.Sprintf("forbidden: user %s has no permission to download", userInRepo.Username)
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg)
} else {
return errors.New("unknow operation")
msg := "system_error: unknow operation"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg)
}
}
4 changes: 2 additions & 2 deletions docs/BasicGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Git LFS initialized.

```
[lfs]
   url = https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}
url = https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}
```

- 或者通过命令行设置仓库中LFS远程地址:
Expand All @@ -63,7 +63,7 @@ git config --local lfs.url https://openeuler-bigfiles.test.osinfra.cn/{owner}/{r
```

> - 当存在.lfsconfig文件时,使用命令行进行LFS远程地址设置的优先级将高于.lfsconfig文件。
> - 在fork一个已经使用第三方LFS服务服务作为LFS远程服务的仓库后,需要手动修改新仓库中LFS远程地址中的{owner}以及{repo},否则会出现权限校验问题**错误代码401**
> - 在fork一个已经使用第三方LFS服务服务作为LFS远程服务的仓库后,需要需手动使用上述命令设置仓库中LFS远程地址,否则可能会出现权限校验问题**错误代码401**
> - url中{owner}/{repo}替换为实际的仓库路径,注意仓库路径的大小写。
- 选择要用LFS追踪的文件
Expand Down
15 changes: 9 additions & 6 deletions docs/QuickStart.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

```
[lfs]
   url = https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}
url = https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}
```

- 或者通过命令行设置仓库中LFS远程地址:
Expand All @@ -22,16 +22,19 @@ $ git config --local lfs.url https://openeuler-bigfiles.test.osinfra.cn/{owner}/
```

> 当存在.lfsconfig文件时,使用命令行进行LFS远程地址设置的优先级将高于.lfsconfig文件。
url中{owner}/{repo}替换为实际的仓库路径,如:openeuler/lfs。由于Gitee默认会将仓库路径中的大写转化为小写,请确认仓库路径的大小写。
> url中{owner}/{repo}替换为实际的仓库路径,如:openeuler/lfs。由于Gitee默认会将仓库路径中的大写转化为小写,请确认仓库路径的大小写。
## 第三方LFS服务与Gitee的使用差异

关于GIT LFS的基本使用请详阅[基础教程](BasicGuide.md)。我们努力使第三方LFS服务与原生LFS服务的使用差异尽可能少,以下是现存的一些差异:

- 当您fork一个仓库:
- 在fork一个已经使用第三方LFS服务作为LFS远程服务的仓库后,需要手动修改新仓库中LFS远程地址中的{owner}以及{repo},否则会出现权限校验问题,**错误代码401**
- 当您使用ssh协议进行克隆或推送:
- 在使用SSH对Gitee仓库进行克隆后,在使用第三方LFS服务作为LFS远程服务时,仍然需要输入账户和密码。
- 当您fork一个仓库:将fork仓库克隆到本地后,需手动使用如下命令修改本地仓库的lfs配置:

```
$ git config --local lfs.url https://openeuler-bigfiles.test.osinfra.cn/{owner}/{repo}
```

- 当您使用ssh协议进行克隆或推送:克隆或推送大文件时仍需输入用户名和密码进行认证。

## 迁移Gitee中使用LFS服务的仓库中的大文件

Expand Down
19 changes: 12 additions & 7 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"os"
"regexp"
"strings"
"time"

"github.com/go-chi/chi"
Expand Down Expand Up @@ -139,18 +140,22 @@ func (s *server) handleBatch(w http.ResponseWriter, r *http.Request) {
userInRepo.Username = username
userInRepo.Password = password
err = s.isAuthorized(userInRepo)
// TODO: 若仓库无lfs服务权限,不能返回401,否则会继续提示输入用户名密码。返回403
if err != nil {
err = fmt.Errorf("unauthorized: %w", err)
}
} else {
err = errors.New("Unauthorized")
err = errors.New("unauthorized: cannot get password")
}
if err != nil {
v := err.Error()
switch {
case strings.HasPrefix(v, "unauthorized") || strings.HasPrefix(v, "not_found"):
w.WriteHeader(401)
case strings.HasPrefix(v, "forbidden"):
w.WriteHeader(403)
default:
w.WriteHeader(500)
}
w.Header().Set("LFS-Authenticate", `Basic realm="Git LFS"`)
w.WriteHeader(401)
must(json.NewEncoder(w).Encode(batch.ErrorResponse{
Message: err.Error(),
Message: v,
}))
return
}
Expand Down

0 comments on commit 1c7ec28

Please sign in to comment.