package devcontainer import ( "strconv" "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/log" web_module "code.gitea.io/gitea/modules/web" Result "code.gitea.io/gitea/routers/entity" context "code.gitea.io/gitea/services/context" gitea_web_context "code.gitea.io/gitea/services/context" devcontainer_service "code.gitea.io/gitea/services/devcontainer" "code.gitea.io/gitea/services/forms" ) // CreateRepoDevcontainer 创建 某用户在某仓库的 DevContainer // // POST /api/devcontainer // 请求体参数: // -- repoId: 需要为哪个仓库创建 DevContainer // -- sshPublicKeyList: 列表,填入用户希望临时使用的SSH会话加密公钥 // 注意:必须携带 用户登录凭证 func CreateRepoDevcontainer(ctx *context.Context) { // 1. 检查用户登录状态,若未登录则返回未授权错误 if ctx == nil || ctx.Doer == nil { Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp) return } // 2. 检查表单校验规则是否失败 if ctx.HasError() { // POST Binding 表单正则表达式校验失败,返回 API 错误信息 failedToValidateFormData := &Result.ResultType{ Code: Result.RespFailedIllegalParams.Code, Msg: Result.RespFailedIllegalParams.Msg, Data: map[string]string{ "ErrorMsg": ctx.GetErrMsg(), }, } failedToValidateFormData.RespondJson2HttpResponseWriter(ctx.Resp) return } // 3. 解析 repoId form := web_module.GetForm(ctx).(*forms.CreateRepoDevcontainerForm) repoId, err := strconv.ParseInt(form.RepoId, 10, 64) if err != nil || repoId <= 0 { failedToParseRepoId := Result.ResultType{ Code: Result.RespFailedIllegalParams.Code, Msg: Result.RespFailedIllegalParams.Msg, Data: map[string]string{ // fix nullptr dereference of `err.Error()` when repoId == 0 "ErrorMsg": "repoId 必须是正数", }, } failedToParseRepoId.RespondJson2HttpResponseWriter(ctx.Resp) return } // 4. 调用 API Service 层创建 DevContainer repo, err := repo.GetRepositoryByID(ctx, repoId) if err != nil { errCreateDevcontainer := Result.ResultType{ Code: Result.RespFailedCreateDevcontainer.Code, Msg: Result.RespFailedCreateDevcontainer.Msg, Data: map[string]string{ "ErrorMsg": "repo not found", }, } errCreateDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp) return } devcontainer_service.CreateDevcontainerConfiguration(repo, ctx.Doer) err = devcontainer_service.CreateDevcontainerAPIService(ctx, repo, ctx.Doer, form.SSHPublicKeyList, false) if err != nil { errCreateDevcontainer := Result.ResultType{ Code: Result.RespFailedCreateDevcontainer.Code, Msg: Result.RespFailedCreateDevcontainer.Msg, Data: map[string]string{ "ErrorMsg": err.Error(), }, } errCreateDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp) return } // 4. 创建 DevContainer 成功,直接返回 Result.RespSuccess.RespondJson2HttpResponseWriter(ctx.Resp) } // GetDevcontainer 查找某用户在某仓库的 DevContainer // // GET /api/devcontainer // 请求体参数: // -- repoId: 需要为哪个仓库创建 DevContainer // -- wait: 是否等待 DevContainer 就绪(默认为 false 直接返回“未就绪”,否则阻塞等待) // -- UserPublicKey // 注意:必须携带 用户登录凭证 func GetDevcontainer(ctx *gitea_web_context.Context) { // 1. 检查用户登录状态,若未登录则返回未授权错误 if ctx == nil || ctx.Doer == nil { Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp) return } // 2. 取得参数 repoIdStr := ctx.FormString("repoId") UserPublicKey := ctx.FormString("userPublicKey") log.Info(UserPublicKey) repoId, err := strconv.ParseInt(repoIdStr, 10, 64) if err != nil || repoId <= 0 { Result.RespFailedIllegalParams.RespondJson2HttpResponseWriter(ctx.Resp) return } repoDevcontainerVO, err := devcontainer_service.OpenDevcontainerAPIService(ctx, ctx.Doer.ID, repoId) if err != nil { failureGetDevcontainer := Result.ResultType{ Code: Result.RespFailedOpenDevcontainer.Code, Msg: Result.RespFailedOpenDevcontainer.Msg, Data: map[string]any{ "ErrorMsg": err.Error(), }, } failureGetDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp) return } // 4. 封装返回成功信息 successGetDevContainer := Result.ResultType{ Code: Result.RespSuccess.Code, Msg: Result.RespSuccess.Msg, Data: repoDevcontainerVO, } successGetDevContainer.RespondJson2HttpResponseWriter(ctx.Resp) } // DeleteRepoDevcontainer 删除某仓库的 DevContainer // // DELETE /api/devcontainer // 请求体参数: // -- repoId: 需要为哪个仓库创建 DevContainer // 注意:必须携带 用户登录凭证 func DeleteRepoDevcontainer(ctx *gitea_web_context.Context) { // 1. 检查用户登录状态,若未登录则返回未授权错误 if ctx == nil || ctx.Doer == nil { Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp) return } // 2. 取得参数 repoId repoIdStr := ctx.FormString("repoId") repoId, err := strconv.ParseInt(repoIdStr, 10, 64) if err != nil || repoId <= 0 { Result.RespFailedIllegalParams.RespondJson2HttpResponseWriter(ctx.Resp) return } err = devcontainer_service.DeleteDevContainer(ctx, ctx.Doer.ID, repoId) if err != nil { failureDeleteDevcontainer := Result.ResultType{ Code: Result.RespFailedDeleteDevcontainer.Code, Msg: Result.RespFailedDeleteDevcontainer.Msg, Data: map[string]any{ "ErrorMsg": err.Error(), }, } failureDeleteDevcontainer.RespondJson2HttpResponseWriter(ctx.Resp) return } // 4. 删除成功,返回提示信息 Result.RespSuccess.RespondJson2HttpResponseWriter(ctx.Resp) } // ListUserDevcontainers 枚举已登录用户所有的 DevContainers // // GET /api/devcontainer/user // 请求输入参数: // - page: 当前第几页(默认第1页),从1开始计数 // - pageSize: 每页记录数(默认值 setting.UI.Admin.DevContainersPagingNum) func ListUserDevcontainers(ctx *gitea_web_context.Context) { // 1. 检查用户登录状态,若未登录则返回未授权错误 if ctx.Doer == nil { Result.RespUnauthorizedFailure.RespondJson2HttpResponseWriter(ctx.Resp) return } // 2. 查询数据库 当前登录用户拥有写入权限的仓库 userPage := ctx.FormInt("page") if userPage <= 0 { userPage = 1 } userPageSize := ctx.FormInt("page_size") if userPageSize <= 0 || userPageSize > 50 { userPageSize = 50 } userDevcontainersVO, err := devcontainer_service.GetDevcontainersList(ctx, ctx.Doer, userPage, userPageSize) if err != nil { resultFailed2ListUserDevcontainerList := Result.ResultType{ Code: Result.RespFailedListUserDevcontainers.Code, Msg: Result.RespFailedListUserDevcontainers.Msg, Data: map[string]string{ "ErrorMsg": err.Error(), }, } resultFailed2ListUserDevcontainerList.RespondJson2HttpResponseWriter(ctx.Resp) return } // 3. 封装VO resultListUserDevcontainersVO := Result.ResultType{ Code: Result.RespSuccess.Code, Msg: Result.RespSuccess.Msg, Data: userDevcontainersVO, } // 4. JSON序列化,写入输出流 responseWriter := ctx.Resp resultListUserDevcontainersVO.RespondJson2HttpResponseWriter(responseWriter) }