Files
devstar/routers/api/devcontainer/devcontainer.go
2025-08-21 21:31:51 +08:00

225 lines
7.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}