| @@ -1,155 +0,0 @@ | |||
| package admin | |||
| import ( | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/auth" | |||
| "code.gitea.io/gitea/modules/context" | |||
| "code.gitea.io/gitea/modules/migrations" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/structs" | |||
| "code.gitea.io/gitea/modules/task" | |||
| "code.gitea.io/gitea/modules/util" | |||
| "code.gitea.io/gitea/routers/response" | |||
| "fmt" | |||
| "net/http" | |||
| "net/url" | |||
| "strings" | |||
| ) | |||
| func MigrateSubmit(ctx *context.APIContext, form auth.MigrateRepoForm) { | |||
| ctxUser, bizErr := checkContextUser(ctx, form.UID) | |||
| if bizErr != nil { | |||
| ctx.JSON(http.StatusOK, response.ResponseError(bizErr)) | |||
| return | |||
| } | |||
| remoteAddr, err := form.ParseRemoteAddr(ctx.User) | |||
| if err != nil { | |||
| if models.IsErrInvalidCloneAddr(err) { | |||
| addrErr := err.(models.ErrInvalidCloneAddr) | |||
| switch { | |||
| case addrErr.IsURLError: | |||
| ctx.JSON(http.StatusOK, response.PARAM_ERROR) | |||
| case addrErr.IsPermissionDenied: | |||
| ctx.JSON(http.StatusOK, response.INSUFFICIENT_PERMISSION) | |||
| case addrErr.IsInvalidPath: | |||
| ctx.JSON(http.StatusOK, response.PARAM_ERROR) | |||
| default: | |||
| ctx.JSON(http.StatusOK, response.SYSTEM_ERROR) | |||
| } | |||
| } else { | |||
| ctx.JSON(http.StatusOK, response.SYSTEM_ERROR) | |||
| } | |||
| return | |||
| } | |||
| var gitServiceType = structs.PlainGitService | |||
| u, err := url.Parse(form.CloneAddr) | |||
| if err == nil && strings.EqualFold(u.Host, "github.com") { | |||
| gitServiceType = structs.GithubService | |||
| } | |||
| var opts = migrations.MigrateOptions{ | |||
| OriginalURL: form.CloneAddr, | |||
| GitServiceType: gitServiceType, | |||
| CloneAddr: remoteAddr, | |||
| RepoName: form.RepoName, | |||
| Alias: form.Alias, | |||
| Description: form.Description, | |||
| Private: form.Private || setting.Repository.ForcePrivate, | |||
| Mirror: form.Mirror, | |||
| AuthUsername: form.AuthUsername, | |||
| AuthPassword: form.AuthPassword, | |||
| Wiki: form.Wiki, | |||
| Issues: form.Issues, | |||
| Milestones: form.Milestones, | |||
| Labels: form.Labels, | |||
| Comments: true, | |||
| PullRequests: form.PullRequests, | |||
| Releases: form.Releases, | |||
| } | |||
| if opts.Mirror { | |||
| opts.Issues = false | |||
| opts.Milestones = false | |||
| opts.Labels = false | |||
| opts.Comments = false | |||
| opts.PullRequests = false | |||
| opts.Releases = false | |||
| } | |||
| err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, opts.Alias) | |||
| if err != nil { | |||
| handleMigrateError(ctx, ctxUser, remoteAddr, err) | |||
| return | |||
| } | |||
| err = task.MigrateRepository(ctx.User, ctxUser, opts) | |||
| if err == nil { | |||
| r := make(map[string]string) | |||
| r["OpenIUrl"] = strings.TrimSuffix(setting.AppURL, "/") + "/" + ctxUser.Name + "/" + opts.RepoName | |||
| r["OriginUrl"] = form.CloneAddr | |||
| ctx.JSON(http.StatusOK, response.SuccessWithData(r)) | |||
| return | |||
| } | |||
| handleMigrateError(ctx, ctxUser, remoteAddr, err) | |||
| } | |||
| func checkContextUser(ctx *context.APIContext, uid int64) (*models.User, *response.BizError) { | |||
| if uid == ctx.User.ID || uid == 0 { | |||
| return ctx.User, nil | |||
| } | |||
| org, err := models.GetUserByID(uid) | |||
| if models.IsErrUserNotExist(err) { | |||
| return ctx.User, nil | |||
| } | |||
| if err != nil { | |||
| return nil, response.SYSTEM_ERROR | |||
| } | |||
| // Check ownership of organization. | |||
| if !org.IsOrganization() { | |||
| return nil, nil | |||
| } | |||
| if !ctx.User.IsAdmin { | |||
| canCreate, err := org.CanCreateOrgRepo(ctx.User.ID) | |||
| if err != nil { | |||
| return nil, response.NewBizError(err) | |||
| } else if !canCreate { | |||
| return nil, response.INSUFFICIENT_PERMISSION | |||
| } | |||
| } | |||
| return org, nil | |||
| } | |||
| func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteAddr string, err error) { | |||
| switch { | |||
| case models.IsErrRepoAlreadyExist(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError("The repository with the same name already exists.")) | |||
| case migrations.IsRateLimitError(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError("Remote visit addressed rate limitation.")) | |||
| case migrations.IsTwoFactorAuthError(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError("Remote visit required two factors authentication.")) | |||
| case models.IsErrReachLimitOfRepo(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("You have already reached your limit of %d repositories.", repoOwner.MaxCreationLimit()))) | |||
| case models.IsErrNameReserved(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("The username '%s' is reserved.", err.(models.ErrNameReserved).Name))) | |||
| case models.IsErrNameCharsNotAllowed(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("The username '%s' contains invalid characters.", err.(models.ErrNameCharsNotAllowed).Name))) | |||
| case models.IsErrNamePatternNotAllowed(err): | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(models.ErrNamePatternNotAllowed).Pattern))) | |||
| default: | |||
| err = util.URLSanitizedError(err, remoteAddr) | |||
| if strings.Contains(err.Error(), "Authentication failed") || | |||
| strings.Contains(err.Error(), "Bad credentials") || | |||
| strings.Contains(err.Error(), "could not read Username") { | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("Authentication failed: %v.", err))) | |||
| } else if strings.Contains(err.Error(), "fatal:") { | |||
| ctx.JSON(http.StatusOK, response.ServerError(fmt.Sprintf("Migration failed: %v.", err))) | |||
| } else { | |||
| ctx.JSON(http.StatusOK, response.ServerError(err.Error())) | |||
| } | |||
| } | |||
| } | |||