mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-02-13 21:00:00 +00:00
Improve repair endpoints (#5767)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -51,7 +51,7 @@ func PostRepo(c *gin.Context) {
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromUser(user)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from user")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ func GetRepoBranches(c *gin.Context) {
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from repo")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -388,8 +388,6 @@ func GetRepoBranches(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
forge.Refresh(c, _forge, _store, repoUser)
|
||||
|
||||
branches, err := _forge.Branches(c, repoUser, repo, session.Pagination(c))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to load branches")
|
||||
@@ -417,7 +415,7 @@ func GetRepoPullRequests(c *gin.Context) {
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from repo")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -455,7 +453,7 @@ func DeleteRepo(c *gin.Context) {
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from repo")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -493,10 +491,13 @@ func DeleteRepo(c *gin.Context) {
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func RepairRepo(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
repairRepo(c, repo, true, false)
|
||||
if c.Writer.Written() {
|
||||
err := repairRepo(c, repo, true)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("repair repo '%s' failed", repo.FullName)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -517,7 +518,7 @@ func MoveRepo(c *gin.Context) {
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from repo")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -635,53 +636,55 @@ func RepairAllRepos(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
failedRepos := make([]int64, 0)
|
||||
for _, r := range repos {
|
||||
repairRepo(c, r, false, true)
|
||||
if c.Writer.Written() {
|
||||
return
|
||||
// updatePermissions is false as RepoListAll does not load permissions
|
||||
updatePermissions := false
|
||||
err := repairRepo(c, r, updatePermissions)
|
||||
if err != nil {
|
||||
failedRepos = append(failedRepos, r.ID)
|
||||
_ = c.Error(err)
|
||||
log.Error().Err(err).Msgf("failed to repair repo '%s'", r.FullName)
|
||||
}
|
||||
}
|
||||
|
||||
c.Status(http.StatusNoContent)
|
||||
if len(failedRepos) > 0 {
|
||||
c.JSON(http.StatusInternalServerError, map[string]any{
|
||||
"error": "failed to repair some repos",
|
||||
"failed_repos": failedRepos,
|
||||
})
|
||||
} else {
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
func repairRepo(c *gin.Context, repo *model.Repo, withPerms, skipOnErr bool) {
|
||||
func repairRepo(c *gin.Context, repo *model.Repo, updatePermissions bool) error {
|
||||
_store := store.FromContext(c)
|
||||
_forge, err := server.Config.Services.Manager.ForgeFromRepo(repo)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cannot get forge from repo")
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
user, err := _store.GetUser(repo.UserID)
|
||||
repoUser, err := repairRepoUser(c, repo, _store)
|
||||
if err != nil {
|
||||
if errors.Is(err, types.RecordNotExist) {
|
||||
oldUserID := repo.UserID
|
||||
user = session.User(c)
|
||||
repo.UserID = user.ID
|
||||
err = _store.UpdateRepo(repo)
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
}
|
||||
log.Debug().Msgf("Could not find repo user with ID %d during repo repair, set to repair request user with ID %d", oldUserID, user.ID)
|
||||
} else {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
log.Error().Err(err).Msgf("cannot assign user to repo '%s'", repo.FullName)
|
||||
return err
|
||||
}
|
||||
|
||||
// creates the jwt token used to verify the repository
|
||||
// refresh user token if necessary
|
||||
forge.Refresh(c, _forge, _store, repoUser)
|
||||
|
||||
// creates a new jwt token used to verify webhook calls
|
||||
t := token.New(token.HookToken)
|
||||
t.Set("repo-forge-remote-id", string(repo.ForgeRemoteID))
|
||||
t.Set("forge-id", strconv.FormatInt(repo.ForgeID, 10))
|
||||
sig, err := t.Sign(repo.Hash)
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// reconstruct the hook url
|
||||
// reconstruct the webhook url
|
||||
host := server.Config.Server.WebhookHost
|
||||
hookURL := fmt.Sprintf(
|
||||
"%s/api/hook?access_token=%s",
|
||||
@@ -689,44 +692,58 @@ func repairRepo(c *gin.Context, repo *model.Repo, withPerms, skipOnErr bool) {
|
||||
sig,
|
||||
)
|
||||
|
||||
from, err := _forge.Repo(c, user, repo.ForgeRemoteID, repo.Owner, repo.Name)
|
||||
from, err := _forge.Repo(c, repoUser, repo.ForgeRemoteID, repo.Owner, repo.Name)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("get repo '%s/%s' from forge", repo.Owner, repo.Name)
|
||||
if !skipOnErr {
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if repo.FullName != from.FullName {
|
||||
// create a redirection
|
||||
err = _store.CreateRedirection(&model.Redirection{RepoID: repo.ID, FullName: repo.FullName})
|
||||
if err != nil {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
repo.Update(from)
|
||||
if err := _store.UpdateRepo(repo); err != nil {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
if withPerms {
|
||||
|
||||
if updatePermissions {
|
||||
repo.Perm.Pull = from.Perm.Pull
|
||||
repo.Perm.Push = from.Perm.Push
|
||||
repo.Perm.Admin = from.Perm.Admin
|
||||
if err := _store.PermUpsert(repo.Perm); err != nil {
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := _forge.Deactivate(c, user, repo, host); err != nil {
|
||||
log.Trace().Err(err).Msgf("deactivate repo '%s' to repair failed", repo.FullName)
|
||||
}
|
||||
if err := _forge.Activate(c, user, repo, hookURL); err != nil {
|
||||
c.String(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
// remove webhook (deactivate) and recreate it (activate)
|
||||
if err := _forge.Deactivate(c, repoUser, repo, host); err != nil {
|
||||
log.Debug().Err(err).Msgf("deactivate repo '%s' to repair failed", repo.FullName)
|
||||
}
|
||||
|
||||
return _forge.Activate(c, repoUser, repo, hookURL)
|
||||
}
|
||||
|
||||
func repairRepoUser(c *gin.Context, repo *model.Repo, _store store.Store) (*model.User, error) {
|
||||
repoUser, err := _store.GetUser(repo.UserID)
|
||||
if err != nil {
|
||||
if errors.Is(err, types.RecordNotExist) {
|
||||
oldUserID := repo.UserID
|
||||
sessionUser := session.User(c)
|
||||
repo.UserID = sessionUser.ID
|
||||
err = _store.UpdateRepo(repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug().Msgf("Could not find repo user with ID %d during repo repair, set to repair request user with ID %d", oldUserID, sessionUser.ID)
|
||||
return sessionUser, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repoUser, nil
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ func Refresh(c context.Context, forge Forge, _store store.Store, user *model.Use
|
||||
return
|
||||
}
|
||||
|
||||
ok, err := refresher.Refresh(c, user)
|
||||
userUpdated, err := refresher.Refresh(c, user)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("refresh oauth token of user '%s' failed", user.Login)
|
||||
} else if ok {
|
||||
} else if userUpdated {
|
||||
if err := _store.UpdateUser(user); err != nil {
|
||||
log.Error().Err(err).Msg("fail to save user to store after refresh oauth token")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user