mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			v1.8.2
			...
			release/v1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					11f6ed4f83 | ||
| 
						 | 
					e94a84248d | ||
| 
						 | 
					cf7a5b3d91 | ||
| 
						 | 
					5d1a8d23b0 | ||
| 
						 | 
					dbd0a2e6dc | ||
| 
						 | 
					7697a282d6 | ||
| 
						 | 
					76e8eec3d9 | ||
| 
						 | 
					10effb396a | ||
| 
						 | 
					5e97b2d00e | ||
| 
						 | 
					873acd884d | 
							
								
								
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -4,6 +4,16 @@ This changelog goes through all the changes that have been made in each release
 | 
			
		||||
without substantial changes to our git log; to see the highlights of what has
 | 
			
		||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
 | 
			
		||||
## [1.8.3](https://github.com/go-gitea/gitea/releases/tag/v1.8.3) - 2019-06-17
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Always set userID on LFS authentication (#7224) (Part of #6993)
 | 
			
		||||
  * Fix LFS Locks over SSH (#6999) (#7223)
 | 
			
		||||
  * Fix duplicated file on pull request conflicted files (#7211) (#7214)
 | 
			
		||||
  * Detect noreply email address as user (#7133) (#7195)
 | 
			
		||||
  * Don't get milestone from DB if ID is zero (#7169) (#7174)
 | 
			
		||||
  * Allow archived repos to be (un)starred and (un)watched (#7163) (#7168)
 | 
			
		||||
  * Fix GCArgs load from ini (#7156) (#7157)
 | 
			
		||||
 | 
			
		||||
## [1.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix possbile mysql invalid connnection error (#7051) (#7071)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										130
									
								
								cmd/serv.go
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								cmd/serv.go
									
									
									
									
									
								
							@@ -217,75 +217,77 @@ func runServ(c *cli.Context) error {
 | 
			
		||||
 | 
			
		||||
	// Allow anonymous clone for public repositories.
 | 
			
		||||
	var (
 | 
			
		||||
		keyID int64
 | 
			
		||||
		user  *models.User
 | 
			
		||||
		keyID  int64
 | 
			
		||||
		user   *models.User
 | 
			
		||||
		userID int64
 | 
			
		||||
	)
 | 
			
		||||
	if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView {
 | 
			
		||||
		keys := strings.Split(c.Args()[0], "-")
 | 
			
		||||
		if len(keys) != 2 {
 | 
			
		||||
			fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
 | 
			
		||||
	keys := strings.Split(c.Args()[0], "-")
 | 
			
		||||
	if len(keys) != 2 {
 | 
			
		||||
		fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
 | 
			
		||||
	}
 | 
			
		||||
	keyID = key.ID
 | 
			
		||||
	userID = key.OwnerID
 | 
			
		||||
 | 
			
		||||
	if key.Type == models.KeyTypeDeploy {
 | 
			
		||||
		// Now we have to get the deploy key for this repo
 | 
			
		||||
		deployKey, err := private.GetDeployKey(key.ID, repo.ID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
 | 
			
		||||
			fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
			
		||||
		}
 | 
			
		||||
		keyID = key.ID
 | 
			
		||||
 | 
			
		||||
		if deployKey == nil {
 | 
			
		||||
			fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if deployKey.Mode < requestedMode {
 | 
			
		||||
			fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Update deploy key activity.
 | 
			
		||||
		if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
 | 
			
		||||
			fail("Internal error", "UpdateDeployKey: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// FIXME: Deploy keys aren't really the owner of the repo pushing changes
 | 
			
		||||
		// however we don't have good way of representing deploy keys in hook.go
 | 
			
		||||
		// so for now use the owner
 | 
			
		||||
		os.Setenv(models.EnvPusherName, username)
 | 
			
		||||
		os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
 | 
			
		||||
		userID = repo.OwnerID
 | 
			
		||||
	} else if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView {
 | 
			
		||||
		// Check deploy key or user key.
 | 
			
		||||
		if key.Type == models.KeyTypeDeploy {
 | 
			
		||||
			// Now we have to get the deploy key for this repo
 | 
			
		||||
			deployKey, err := private.GetDeployKey(key.ID, repo.ID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if deployKey == nil {
 | 
			
		||||
				fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if deployKey.Mode < requestedMode {
 | 
			
		||||
				fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Update deploy key activity.
 | 
			
		||||
			if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
 | 
			
		||||
				fail("Internal error", "UpdateDeployKey: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// FIXME: Deploy keys aren't really the owner of the repo pushing changes
 | 
			
		||||
			// however we don't have good way of representing deploy keys in hook.go
 | 
			
		||||
			// so for now use the owner
 | 
			
		||||
			os.Setenv(models.EnvPusherName, username)
 | 
			
		||||
			os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
 | 
			
		||||
		} else {
 | 
			
		||||
			user, err = private.GetUserByKeyID(key.ID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !user.IsActive || user.ProhibitLogin {
 | 
			
		||||
				fail("Your account is not active or has been disabled by Administrator",
 | 
			
		||||
					"User %s is disabled and have no access to repository %s",
 | 
			
		||||
					user.Name, repoPath)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fail("Internal error", "Failed to check access: %v", err)
 | 
			
		||||
			} else if *mode < requestedMode {
 | 
			
		||||
				clientMessage := accessDenied
 | 
			
		||||
				if *mode >= models.AccessModeRead {
 | 
			
		||||
					clientMessage = "You do not have sufficient authorization for this action"
 | 
			
		||||
				}
 | 
			
		||||
				fail(clientMessage,
 | 
			
		||||
					"User %s does not have level %v access to repository %s's "+unitName,
 | 
			
		||||
					user.Name, requestedMode, repoPath)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			os.Setenv(models.EnvPusherName, user.Name)
 | 
			
		||||
			os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
 | 
			
		||||
		user, err = private.GetUserByKeyID(key.ID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !user.IsActive || user.ProhibitLogin {
 | 
			
		||||
			fail("Your account is not active or has been disabled by Administrator",
 | 
			
		||||
				"User %s is disabled and have no access to repository %s",
 | 
			
		||||
				user.Name, repoPath)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fail("Internal error", "Failed to check access: %v", err)
 | 
			
		||||
		} else if *mode < requestedMode {
 | 
			
		||||
			clientMessage := accessDenied
 | 
			
		||||
			if *mode >= models.AccessModeRead {
 | 
			
		||||
				clientMessage = "You do not have sufficient authorization for this action"
 | 
			
		||||
			}
 | 
			
		||||
			fail(clientMessage,
 | 
			
		||||
				"User %s does not have level %v access to repository %s's "+unitName,
 | 
			
		||||
				user.Name, requestedMode, repoPath)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		os.Setenv(models.EnvPusherName, user.Name)
 | 
			
		||||
		os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//LFS token authentication
 | 
			
		||||
@@ -299,8 +301,8 @@ func runServ(c *cli.Context) error {
 | 
			
		||||
			"exp":  now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
 | 
			
		||||
			"nbf":  now.Unix(),
 | 
			
		||||
		}
 | 
			
		||||
		if user != nil {
 | 
			
		||||
			claims["user"] = user.ID
 | 
			
		||||
		if userID > 0 {
 | 
			
		||||
			claims["user"] = userID
 | 
			
		||||
		}
 | 
			
		||||
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,10 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
					little = commitAndPush(t, littleSize, dstPath)
 | 
			
		||||
				})
 | 
			
		||||
				t.Run("Big", func(t *testing.T) {
 | 
			
		||||
					if testing.Short() {
 | 
			
		||||
						t.Skip("skipping test in short mode.")
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					big = commitAndPush(t, bigSize, dstPath)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
@@ -77,9 +81,15 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
 | 
			
		||||
				t.Run("Little", func(t *testing.T) {
 | 
			
		||||
					littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
			
		||||
					lockFileTest(t, littleLFS, dstPath)
 | 
			
		||||
				})
 | 
			
		||||
				t.Run("Big", func(t *testing.T) {
 | 
			
		||||
					if testing.Short() {
 | 
			
		||||
						t.Skip("skipping test in short mode.")
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
			
		||||
					lockFileTest(t, bigLFS, dstPath)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
			t.Run("Locks", func(t *testing.T) {
 | 
			
		||||
@@ -94,19 +104,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
			resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", big))
 | 
			
		||||
			nilResp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, nilResp.Length)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", littleLFS))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
			
		||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", bigLFS))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
			if !testing.Short() {
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", big))
 | 
			
		||||
				nilResp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, nilResp.Length)
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		})
 | 
			
		||||
		t.Run("Media", func(t *testing.T) {
 | 
			
		||||
@@ -117,17 +129,19 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
			resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", big))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", littleLFS))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", bigLFS))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
			if !testing.Short() {
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", big))
 | 
			
		||||
				resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
@@ -160,6 +174,10 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
						little = commitAndPush(t, littleSize, dstPath)
 | 
			
		||||
					})
 | 
			
		||||
					t.Run("Big", func(t *testing.T) {
 | 
			
		||||
						if testing.Short() {
 | 
			
		||||
							t.Skip("skipping test in short mode.")
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						big = commitAndPush(t, bigSize, dstPath)
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
@@ -176,9 +194,16 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
 | 
			
		||||
					t.Run("Little", func(t *testing.T) {
 | 
			
		||||
						littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
			
		||||
						lockFileTest(t, littleLFS, dstPath)
 | 
			
		||||
 | 
			
		||||
					})
 | 
			
		||||
					t.Run("Big", func(t *testing.T) {
 | 
			
		||||
						if testing.Short() {
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
						bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
			
		||||
						lockFileTest(t, bigLFS, dstPath)
 | 
			
		||||
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
				t.Run("Locks", func(t *testing.T) {
 | 
			
		||||
@@ -193,20 +218,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
				resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", big))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", littleLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
			
		||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
				if !testing.Short() {
 | 
			
		||||
					req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", big))
 | 
			
		||||
					resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
					assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
					req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", bigLFS))
 | 
			
		||||
					resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
					assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
					assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
			t.Run("Media", func(t *testing.T) {
 | 
			
		||||
				session := loginUser(t, "user2")
 | 
			
		||||
@@ -216,17 +242,19 @@ func testGit(t *testing.T, u *url.URL) {
 | 
			
		||||
				resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", big))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", littleLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
				if !testing.Short() {
 | 
			
		||||
					req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", big))
 | 
			
		||||
					resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
					assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
					req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", bigLFS))
 | 
			
		||||
					resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
					assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
		})
 | 
			
		||||
@@ -243,15 +271,17 @@ func ensureAnonymousClone(t *testing.T, u *url.URL) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lockTest(t *testing.T, remote, repoPath string) {
 | 
			
		||||
	_, err := git.NewCommand("remote").AddArguments("set-url", "origin", remote).RunInDir(repoPath) //TODO add test ssh git-lfs-creds
 | 
			
		||||
	lockFileTest(t, "README.md", repoPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lockFileTest(t *testing.T, filename, repoPath string) {
 | 
			
		||||
	_, err := git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("lock", filename).RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("lock", "README.md").RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("unlock", "README.md").RunInDir(repoPath)
 | 
			
		||||
	_, err = git.NewCommand("lfs").AddArguments("unlock", filename).RunInDir(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -861,7 +861,17 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
 | 
			
		||||
					line := scanner.Text()
 | 
			
		||||
 | 
			
		||||
					if strings.HasPrefix(line, prefix) {
 | 
			
		||||
						pr.ConflictedFiles = append(pr.ConflictedFiles, strings.TrimSpace(strings.Split(line[len(prefix):], ":")[0]))
 | 
			
		||||
						var found bool
 | 
			
		||||
						var filepath = strings.TrimSpace(strings.Split(line[len(prefix):], ":")[0])
 | 
			
		||||
						for _, f := range pr.ConflictedFiles {
 | 
			
		||||
							if f == filepath {
 | 
			
		||||
								found = true
 | 
			
		||||
								break
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						if !found {
 | 
			
		||||
							pr.ConflictedFiles = append(pr.ConflictedFiles, filepath)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					// only list 10 conflicted files
 | 
			
		||||
					if len(pr.ConflictedFiles) >= 10 {
 | 
			
		||||
 
 | 
			
		||||
@@ -1346,6 +1346,19 @@ func GetUserByEmail(email string) (*User, error) {
 | 
			
		||||
		return GetUserByID(emailAddress.UID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Finally, if email address is the protected email address:
 | 
			
		||||
	if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) {
 | 
			
		||||
		username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress))
 | 
			
		||||
		user := &User{LowerName: username}
 | 
			
		||||
		has, err := x.Get(user)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if has {
 | 
			
		||||
			return user, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, ErrUserNotExist{0, email, 0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/modules/context"
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/sdk/gitea"
 | 
			
		||||
)
 | 
			
		||||
@@ -44,7 +45,7 @@ func checkIsValidRequest(ctx *context.Context, post bool) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleLockListOut(ctx *context.Context, lock *models.LFSLock, err error) {
 | 
			
		||||
func handleLockListOut(ctx *context.Context, repo *models.Repository, lock *models.LFSLock, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrLFSLockNotExist(err) {
 | 
			
		||||
			ctx.JSON(200, api.LFSLockList{
 | 
			
		||||
@@ -57,7 +58,7 @@ func handleLockListOut(ctx *context.Context, lock *models.LFSLock, err error) {
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if ctx.Repo.Repository.ID != lock.RepoID {
 | 
			
		||||
	if repo.ID != lock.RepoID {
 | 
			
		||||
		ctx.JSON(200, api.LFSLockList{
 | 
			
		||||
			Locks: []*api.LFSLock{},
 | 
			
		||||
		})
 | 
			
		||||
@@ -75,17 +76,21 @@ func GetListLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Type", metaMediaType)
 | 
			
		||||
 | 
			
		||||
	err := models.CheckLFSAccessForRepo(ctx.User, ctx.Repo.Repository, models.AccessModeRead)
 | 
			
		||||
	rv := unpack(ctx)
 | 
			
		||||
 | 
			
		||||
	repository, err := models.GetRepositoryByOwnerAndName(rv.User, rv.Repo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrLFSUnauthorizedAction(err) {
 | 
			
		||||
			ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
			ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
				Message: "You must have pull access to list locks : " + err.Error(),
 | 
			
		||||
			})
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.JSON(500, api.LFSLockError{
 | 
			
		||||
			Message: "unable to list lock : " + err.Error(),
 | 
			
		||||
		log.Debug("Could not find repository: %s/%s - %s", rv.User, rv.Repo, err)
 | 
			
		||||
		writeStatus(ctx, 404)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	repository.MustOwner()
 | 
			
		||||
 | 
			
		||||
	authenticated := authenticate(ctx, repository, rv.Authorization, false)
 | 
			
		||||
	if !authenticated {
 | 
			
		||||
		ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
		ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
			Message: "You must have pull access to list locks",
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
@@ -100,19 +105,19 @@ func GetListLockHandler(ctx *context.Context) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		lock, err := models.GetLFSLockByID(int64(v))
 | 
			
		||||
		handleLockListOut(ctx, lock, err)
 | 
			
		||||
		handleLockListOut(ctx, repository, lock, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	path := ctx.Query("path")
 | 
			
		||||
	if path != "" { //Case where we request a specific id
 | 
			
		||||
		lock, err := models.GetLFSLock(ctx.Repo.Repository, path)
 | 
			
		||||
		handleLockListOut(ctx, lock, err)
 | 
			
		||||
		lock, err := models.GetLFSLock(repository, path)
 | 
			
		||||
		handleLockListOut(ctx, repository, lock, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//If no query params path or id
 | 
			
		||||
	lockList, err := models.GetLFSLockByRepoID(ctx.Repo.Repository.ID)
 | 
			
		||||
	lockList, err := models.GetLFSLockByRepoID(repository.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.JSON(500, api.LFSLockError{
 | 
			
		||||
			Message: "unable to list locks : " + err.Error(),
 | 
			
		||||
@@ -135,16 +140,36 @@ func PostLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Type", metaMediaType)
 | 
			
		||||
 | 
			
		||||
	userName := ctx.Params("username")
 | 
			
		||||
	repoName := strings.TrimSuffix(ctx.Params("reponame"), ".git")
 | 
			
		||||
	authorization := ctx.Req.Header.Get("Authorization")
 | 
			
		||||
 | 
			
		||||
	repository, err := models.GetRepositoryByOwnerAndName(userName, repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Debug("Could not find repository: %s/%s - %s", userName, repoName, err)
 | 
			
		||||
		writeStatus(ctx, 404)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	repository.MustOwner()
 | 
			
		||||
 | 
			
		||||
	authenticated := authenticate(ctx, repository, authorization, true)
 | 
			
		||||
	if !authenticated {
 | 
			
		||||
		ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
		ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
			Message: "You must have push access to create locks",
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var req api.LFSLockRequest
 | 
			
		||||
	dec := json.NewDecoder(ctx.Req.Body().ReadCloser())
 | 
			
		||||
	err := dec.Decode(&req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	if err := dec.Decode(&req); err != nil {
 | 
			
		||||
		writeStatus(ctx, 400)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lock, err := models.CreateLFSLock(&models.LFSLock{
 | 
			
		||||
		Repo:  ctx.Repo.Repository,
 | 
			
		||||
		Repo:  repository,
 | 
			
		||||
		Path:  req.Path,
 | 
			
		||||
		Owner: ctx.User,
 | 
			
		||||
	})
 | 
			
		||||
@@ -178,23 +203,29 @@ func VerifyLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Type", metaMediaType)
 | 
			
		||||
 | 
			
		||||
	err := models.CheckLFSAccessForRepo(ctx.User, ctx.Repo.Repository, models.AccessModeWrite)
 | 
			
		||||
	userName := ctx.Params("username")
 | 
			
		||||
	repoName := strings.TrimSuffix(ctx.Params("reponame"), ".git")
 | 
			
		||||
	authorization := ctx.Req.Header.Get("Authorization")
 | 
			
		||||
 | 
			
		||||
	repository, err := models.GetRepositoryByOwnerAndName(userName, repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrLFSUnauthorizedAction(err) {
 | 
			
		||||
			ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
			ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
				Message: "You must have push access to verify locks : " + err.Error(),
 | 
			
		||||
			})
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.JSON(500, api.LFSLockError{
 | 
			
		||||
			Message: "unable to verify lock : " + err.Error(),
 | 
			
		||||
		log.Debug("Could not find repository: %s/%s - %s", userName, repoName, err)
 | 
			
		||||
		writeStatus(ctx, 404)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	repository.MustOwner()
 | 
			
		||||
 | 
			
		||||
	authenticated := authenticate(ctx, repository, authorization, true)
 | 
			
		||||
	if !authenticated {
 | 
			
		||||
		ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
		ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
			Message: "You must have push access to verify locks",
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//TODO handle body json cursor and limit
 | 
			
		||||
	lockList, err := models.GetLFSLockByRepoID(ctx.Repo.Repository.ID)
 | 
			
		||||
	lockList, err := models.GetLFSLockByRepoID(repository.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.JSON(500, api.LFSLockError{
 | 
			
		||||
			Message: "unable to list locks : " + err.Error(),
 | 
			
		||||
@@ -223,10 +254,30 @@ func UnLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Resp.Header().Set("Content-Type", metaMediaType)
 | 
			
		||||
 | 
			
		||||
	userName := ctx.Params("username")
 | 
			
		||||
	repoName := strings.TrimSuffix(ctx.Params("reponame"), ".git")
 | 
			
		||||
	authorization := ctx.Req.Header.Get("Authorization")
 | 
			
		||||
 | 
			
		||||
	repository, err := models.GetRepositoryByOwnerAndName(userName, repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Debug("Could not find repository: %s/%s - %s", userName, repoName, err)
 | 
			
		||||
		writeStatus(ctx, 404)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	repository.MustOwner()
 | 
			
		||||
 | 
			
		||||
	authenticated := authenticate(ctx, repository, authorization, true)
 | 
			
		||||
	if !authenticated {
 | 
			
		||||
		ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
 | 
			
		||||
		ctx.JSON(401, api.LFSLockError{
 | 
			
		||||
			Message: "You must have push access to delete locks",
 | 
			
		||||
		})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var req api.LFSLockDeleteRequest
 | 
			
		||||
	dec := json.NewDecoder(ctx.Req.Body().ReadCloser())
 | 
			
		||||
	err := dec.Decode(&req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	if err := dec.Decode(&req); err != nil {
 | 
			
		||||
		writeStatus(ctx, 400)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ var (
 | 
			
		||||
		MaxGitDiffLines          int
 | 
			
		||||
		MaxGitDiffLineCharacters int
 | 
			
		||||
		MaxGitDiffFiles          int
 | 
			
		||||
		GCArgs                   []string `delim:" "`
 | 
			
		||||
		GCArgs                   []string `ini:"GC_ARGS" delim:" "`
 | 
			
		||||
		Timeout                  struct {
 | 
			
		||||
			Default int
 | 
			
		||||
			Migrate int
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -23,7 +23,7 @@
 | 
			
		||||
                            border-bottom: 1px solid #eaeaea;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        .octicon {
 | 
			
		||||
                        .octicon, .fa {
 | 
			
		||||
                            margin-left: 1px;
 | 
			
		||||
                            margin-right: 5px;
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -698,14 +698,14 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
			
		||||
					Delete(reqToken(), reqOrgMembership(), org.ConcealMember)
 | 
			
		||||
			})
 | 
			
		||||
			m.Combo("/teams", reqToken(), reqOrgMembership()).Get(org.ListTeams).
 | 
			
		||||
				Post(bind(api.CreateTeamOption{}), org.CreateTeam)
 | 
			
		||||
				Post(reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
 | 
			
		||||
			m.Group("/hooks", func() {
 | 
			
		||||
				m.Combo("").Get(org.ListHooks).
 | 
			
		||||
					Post(bind(api.CreateHookOption{}), org.CreateHook)
 | 
			
		||||
				m.Combo("/:id").Get(org.GetHook).
 | 
			
		||||
					Patch(reqOrgOwnership(), bind(api.EditHookOption{}), org.EditHook).
 | 
			
		||||
					Delete(reqOrgOwnership(), org.DeleteHook)
 | 
			
		||||
			}, reqToken(), reqOrgMembership())
 | 
			
		||||
					Patch(bind(api.EditHookOption{}), org.EditHook).
 | 
			
		||||
					Delete(org.DeleteHook)
 | 
			
		||||
			}, reqToken(), reqOrgOwnership())
 | 
			
		||||
		}, orgAssignment(true))
 | 
			
		||||
		m.Group("/teams/:teamid", func() {
 | 
			
		||||
			m.Combo("").Get(org.GetTeam).
 | 
			
		||||
 
 | 
			
		||||
@@ -406,12 +406,14 @@ func NewIssue(ctx *context.Context) {
 | 
			
		||||
	ctx.Data["BodyQuery"] = body
 | 
			
		||||
 | 
			
		||||
	milestoneID := ctx.QueryInt64("milestone")
 | 
			
		||||
	milestone, err := models.GetMilestoneByID(milestoneID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error(4, "GetMilestoneByID: %d: %v", milestoneID, err)
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Data["milestone_id"] = milestoneID
 | 
			
		||||
		ctx.Data["Milestone"] = milestone
 | 
			
		||||
	if milestoneID > 0 {
 | 
			
		||||
		milestone, err := models.GetMilestoneByID(milestoneID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error(4, "GetMilestoneByID: %d: %v", milestoneID, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Data["milestone_id"] = milestoneID
 | 
			
		||||
			ctx.Data["Milestone"] = milestone
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates)
 | 
			
		||||
 
 | 
			
		||||
@@ -578,7 +578,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
			
		||||
		})
 | 
			
		||||
	}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.UnitTypes(), context.RepoRef())
 | 
			
		||||
 | 
			
		||||
	m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), context.RepoMustNotBeArchived(), repo.Action)
 | 
			
		||||
	m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
 | 
			
		||||
 | 
			
		||||
	m.Group("/:username/:reponame", func() {
 | 
			
		||||
		m.Group("/issues", func() {
 | 
			
		||||
@@ -827,7 +827,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
			
		||||
					m.Post("/", lfs.PostLockHandler)
 | 
			
		||||
					m.Post("/verify", lfs.VerifyLockHandler)
 | 
			
		||||
					m.Post("/:lid/unlock", lfs.UnLockHandler)
 | 
			
		||||
				}, context.RepoAssignment())
 | 
			
		||||
				})
 | 
			
		||||
				m.Any("/*", func(ctx *context.Context) {
 | 
			
		||||
					ctx.NotFound("", nil)
 | 
			
		||||
				})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user