Skip to content

Commit

Permalink
Add default token (#35)
Browse files Browse the repository at this point in the history
* add: add default token

add default token

* edit: edit github_test.go

edit github_test.go

* edit: 规范代码

按codearts代码检查结果规范代码

* add: add test

add test

* add: add test

add test

* edit: fmt gitee.go

修改gitee.go文件,规范代码

* edit: edit gitee.go

修改gitee.go文件,声明字符串常量时使用const
  • Loading branch information
Zherphy authored Nov 30, 2024
1 parent a4d33e6 commit 5fe05cb
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 43 deletions.
85 changes: 56 additions & 29 deletions auth/gitee.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
var (
clientId string
clientSecret string
defaultToken string
)

var (
Expand All @@ -23,6 +24,11 @@ var (
downloadPermissions = []string{"admin", "developer", "read"}
)

const contentType = "Content-Type"
const verifyLog = "verifyUser"
const appendPathAccessToken = "?access_token="
const formatLogString = "%s | %s"

type giteeUser struct {
Permission string `json:"permission"`
}
Expand Down Expand Up @@ -64,6 +70,13 @@ func Init(cfg *config.Config) error {
return errors.New("client secret required")
}
}
defaultToken = cfg.DefaultToken
if defaultToken == "" {
defaultToken = os.Getenv("DEFAULT_TOKEN")
if defaultToken == "" {
return errors.New("default token required")
}
}

return nil
}
Expand All @@ -90,14 +103,17 @@ func GiteeAuth() func(UserInRepo) error {
// CheckRepoOwner checks whether the owner of a repo is allowed to use lfs server
func CheckRepoOwner(userInRepo UserInRepo) error {
path := fmt.Sprintf(
"https://gitee.com/api/v5/repos/%s/%s",
"https://gitee.com/api/v5/repos/%s/%s%s",
userInRepo.Owner,
userInRepo.Repo,
appendPathAccessToken,
)
if userInRepo.Token != "" {
path += fmt.Sprintf("?access_token=%s", userInRepo.Token)
path += userInRepo.Token
} else {
path += defaultToken
}
headers := http.Header{"Content-Type": []string{"application/json;charset=UTF-8"}}
headers := http.Header{contentType: []string{"application/json;charset=UTF-8"}}
repo := new(Repo)
err := getParsedResponse("GET", path, headers, nil, &repo)
if err != nil {
Expand Down Expand Up @@ -133,7 +149,7 @@ func getToken(username, password string) (string, error) {
form.Add("client_secret", clientSecret)

path := "https://gitee.com/oauth/token"
headers := http.Header{"Content-Type": []string{"application/x-www-form-urlencoded"}}
headers := http.Header{contentType: []string{"application/x-www-form-urlencoded"}}
accessToken := new(AccessToken)
err := getParsedResponse("POST", path, headers, strings.NewReader(form.Encode()), &accessToken)
if err != nil {
Expand All @@ -147,48 +163,59 @@ func getToken(username, password string) (string, error) {
// verifyUser verifies user permission in repo by access_token and operation
func verifyUser(userInRepo UserInRepo) error {
path := fmt.Sprintf(
"https://gitee.com/api/v5/repos/%s/%s/collaborators/%s/permission",
"https://gitee.com/api/v5/repos/%s/%s/collaborators/%s/permission%s",
userInRepo.Owner,
userInRepo.Repo,
userInRepo.Username,
appendPathAccessToken,
)
if userInRepo.Token != "" {
path += fmt.Sprintf("?access_token=%s", userInRepo.Token)
path += userInRepo.Token
} else {
path += defaultToken
}
headers := http.Header{"Content-Type": []string{"application/json;charset=UTF-8"}}
headers := http.Header{contentType: []string{"application/json;charset=UTF-8"}}
giteeUser := new(giteeUser)
err := getParsedResponse("GET", path, headers, nil, &giteeUser)
if err != nil {
msg := err.Error() + ": verify user permission failed"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
logrus.Error(fmt.Sprintf(formatLogString, verifyLog, msg))
return errors.New(msg)
}

if userInRepo.Operation == "upload" {
for _, v := range uploadPermissions {
if giteeUser.Permission == v {
return nil
}
}
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://artifacts.openeuler.openatom.cn/{owner}/{repo}`" +
",\n其中{owner}/{repo}请改为您fork之后的仓库的名称"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg + remindMsg)
return verifyUserUpload(giteeUser, userInRepo)
} else if userInRepo.Operation == "download" {
for _, v := range downloadPermissions {
if giteeUser.Permission == v {
return nil
}
}
msg := fmt.Sprintf("forbidden: user %s has no permission to download", userInRepo.Username)
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
return errors.New(msg)
return verifyUserDownload(giteeUser, userInRepo)
} else {
msg := "system_error: unknow operation"
logrus.Error(fmt.Sprintf("verifyUser | %s", msg))
logrus.Error(fmt.Sprintf(formatLogString, verifyLog, msg))
return errors.New(msg)
}
}

func verifyUserUpload(giteeUser *giteeUser, userInRepo UserInRepo) error {
for _, v := range uploadPermissions {
if giteeUser.Permission == v {
return nil
}
}
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://artlfs.openeuler.openatom.cn/{owner}/{repo}`" +
",\n其中{owner}/{repo}请改为您fork之后的仓库的名称"
logrus.Error(fmt.Sprintf(formatLogString, verifyLog, msg))
return errors.New(msg + remindMsg)
}

func verifyUserDownload(giteeUser *giteeUser, userInRepo UserInRepo) error {
for _, v := range downloadPermissions {
if giteeUser.Permission == v {
return nil
}
}
msg := fmt.Sprintf("forbidden: user %s has no permission to download", userInRepo.Username)
logrus.Error(fmt.Sprintf(formatLogString, verifyLog, msg))
return errors.New(msg)
}
47 changes: 41 additions & 6 deletions auth/gitee_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package auth

import (
"github.com/metalogical/BigFiles/config"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -10,23 +11,49 @@ import (
// SuiteGitee used for testing
type SuiteGitee struct {
suite.Suite
Repo string
Owner string
cfg config.Config
Repo string
Owner string
UserName string
Password string
}

// SetupSuite used for testing
func (s *SuiteGitee) SetupSuite() {
s.Repo = "software-package-server"
s.Owner = "src-openeuler"
s.UserName = "user"
s.Password = "wrong_pwd"
s.cfg = config.Config{
ClientId: "clientId",
ClientSecret: "clientSecret",
DefaultToken: "defaultToken",
}
}

func (s *SuiteGitee) TestInit() {
//Init success
err := Init(&s.cfg)
assert.Nil(s.T(), err)
}

// TearDownSuite used for testing
func (s *SuiteGitee) TearDownSuite() {
func (s *SuiteGitee) TestGiteeAuth() {
// GiteeAuth fail
userInRepo := UserInRepo{
Repo: s.Repo,
Owner: s.Owner,
Username: s.UserName,
Password: s.Password,
Operation: "download",
}
giteeAuth := GiteeAuth()
err := giteeAuth(userInRepo)
assert.NotNil(s.T(), err)
}

func (s *SuiteGitee) TestGetToken() {
// getToken fail
token, err := getToken("user", "wrong_pwd")
token, err := getToken(s.UserName, s.Password)
assert.Equal(s.T(), "", token)
assert.NotNil(s.T(), err.Error())
}
Expand All @@ -36,14 +63,16 @@ func (s *SuiteGitee) TestCheckRepoOwner() {
userInRepo := UserInRepo{
Repo: s.Repo,
Owner: s.Owner,
Token: s.cfg.DefaultToken,
}
err := CheckRepoOwner(userInRepo)
assert.Nil(s.T(), err)
assert.NotNil(s.T(), err)

// check no_exist repo
userInRepo = UserInRepo{
Repo: "repo",
Owner: "owner",
Token: s.cfg.DefaultToken,
}
err = CheckRepoOwner(userInRepo)
assert.NotNil(s.T(), err)
Expand All @@ -53,11 +82,17 @@ func (s *SuiteGitee) TestVerifyUser() {
userInRepo := UserInRepo{
Repo: s.Repo,
Owner: s.Owner,
Username: s.UserName,
Operation: "download",
Token: s.cfg.DefaultToken,
}

err := verifyUser(userInRepo)
assert.NotNil(s.T(), err)

userInRepo.Operation = "upload"
err = verifyUser(userInRepo)
assert.NotNil(s.T(), err)
}

func TestGitee(t *testing.T) {
Expand Down
4 changes: 0 additions & 4 deletions auth/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ func (s *SuiteGithub) SetupSuite() {
s.Password = "password"
}

// TearDownSuite used for testing
func (s *SuiteGithub) TearDownSuite() {
}

func (s *SuiteGithub) TestStatic() {
// Static success
static := Static(s.Username, s.Password)
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Config struct {
ObsAccessKeyId string `json:"OBS_ACCESS_KEY_ID"`
ObsSecretAccessKey string `json:"OBS_SECRET_ACCESS_KEY"`
ValidateConfig ValidateConfig `json:"VALIDATE_REGEXP"`
DefaultToken string `json:"DEFAULT_TOKEN"`
}

type ValidateConfig struct {
Expand Down
13 changes: 9 additions & 4 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

var ObsPutLimit int = 5*int(math.Pow10(9)) - 1 // 5GB - 1
var oidRegexp = regexp.MustCompile("^[a-f0-9]{64}$")
var contentType = "Content-Type"

type Options struct {
// required
Expand Down Expand Up @@ -114,7 +115,7 @@ func (s *server) key(oid string) string {
}

func (s *server) handleBatch(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/vnd.git-lfs+json")
w.Header().Set(contentType, "application/vnd.git-lfs+json")
w.Header().Set("X-Content-Type-Options", "nosniff")

var req batch.Request
Expand Down Expand Up @@ -169,6 +170,8 @@ func (s *server) handleBatch(w http.ResponseWriter, r *http.Request) {
s.downloadObject(&in, out)
case "upload":
s.uploadObject(&in, out)
default:
continue
}
}
must(json.NewEncoder(w).Encode(resp))
Expand Down Expand Up @@ -228,13 +231,15 @@ func (s *server) downloadObject(in *batch.RequestObject, out *batch.Object) {
Code: 422,
Message: "found object with wrong size",
}
} else {
logrus.Infof("Metadata check pass, Size check pass")
}
getObjectInput := &obs.CreateSignedUrlInput{}
getObjectInput.Method = obs.HttpMethodGet
getObjectInput.Bucket = s.bucket
getObjectInput.Key = s.key(in.OID)
getObjectInput.Expires = int(s.ttl / time.Second)
getObjectInput.Headers = map[string]string{"Content-Type": "application/octet-stream"}
getObjectInput.Headers = map[string]string{contentType: "application/octet-stream"}
// 生成下载对象的带授权信息的URL
v := s.generateDownloadUrl(getObjectInput)

Expand All @@ -261,7 +266,7 @@ func (s *server) uploadObject(in *batch.RequestObject, out *batch.Object) {
putObjectInput.Bucket = s.bucket
putObjectInput.Key = s.key(in.OID)
putObjectInput.Expires = int(s.ttl / time.Second)
putObjectInput.Headers = map[string]string{"Content-Type": "application/octet-stream"}
putObjectInput.Headers = map[string]string{contentType: "application/octet-stream"}
putObjectOutput, err := s.client.CreateSignedUrl(putObjectInput)
if err != nil {
panic(err)
Expand Down Expand Up @@ -300,7 +305,7 @@ func (s *server) healthCheck(w http.ResponseWriter, r *http.Request) {
Data: "healthCheck success",
}

w.Header().Set("Content-Type", "application/json")
w.Header().Set(contentType, "application/json")
w.WriteHeader(http.StatusOK)
must(json.NewEncoder(w).Encode(response))
}
Expand Down

0 comments on commit 5fe05cb

Please sign in to comment.