* DELETE /api/devcontainer?repoId=${repoId} 删除 DevContainer
* refactor
* GET /api/devcontainer?repoId=${repoId}&wait=true 阻塞式等待打开就绪的 DevContainer
* POST /api/devcontainer 创建 DevContainer
* refactored the code
* Updated context usage with cancel function
* 预留接口,适配单机版 DevStar DevContainer
* bugFix: context canceled while deleting k8s CRD DevcontainerApp
* 用户界面删除 k8s CRD DevContainer
* 用户界面创建 DevContainer 并更新 NodePort
* 完成用户界面创建 DevContainer
* transplant test code into DevStar Studio
* refactored API router to /routers/api
* 更改 DevContainer Doc
* 更改 DevContainer namespace
* 特殊仓库重定向
* [Doc] 更新 Kubernetes 部署 DevStar Studio 文档说明,特别是 namespace 管理
* [Doc] 更新 CI脚本说明
* Revert "optimized CI workflow"
* optimized CI workflow
* fix typo
* [feature test]: 测试 Pod 内使用 Kubernetes Operator 功能
* [Optimization] error msg for archived repo
* [Optimization]: display detailed err msg on creating devContainer for …
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||
// SPDX-License-Identifier: MIT
|
||
|
||
package validation
|
||
|
||
import (
|
||
"net"
|
||
"net/url"
|
||
"regexp"
|
||
"strings"
|
||
|
||
"code.gitea.io/gitea/modules/setting"
|
||
|
||
"github.com/gobwas/glob"
|
||
)
|
||
|
||
var externalTrackerRegex = regexp.MustCompile(`({?)(?:user|repo|index)+?(}?)`)
|
||
|
||
func isLoopbackIP(ip string) bool {
|
||
return net.ParseIP(ip).IsLoopback()
|
||
}
|
||
|
||
// IsValidURL checks if URL is valid
|
||
func IsValidURL(uri string) bool {
|
||
if u, err := url.ParseRequestURI(uri); err != nil ||
|
||
(u.Scheme != "http" && u.Scheme != "https") ||
|
||
!validPort(portOnly(u.Host)) {
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// IsValidSiteURL checks if URL is valid
|
||
func IsValidSiteURL(uri string) bool {
|
||
u, err := url.ParseRequestURI(uri)
|
||
if err != nil {
|
||
return false
|
||
}
|
||
|
||
if !validPort(portOnly(u.Host)) {
|
||
return false
|
||
}
|
||
|
||
for _, scheme := range setting.Service.ValidSiteURLSchemes {
|
||
if scheme == u.Scheme {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsEmailDomainListed checks whether the domain of an email address
|
||
// matches a list of domains
|
||
func IsEmailDomainListed(globs []glob.Glob, email string) bool {
|
||
if len(globs) == 0 {
|
||
return false
|
||
}
|
||
|
||
n := strings.LastIndex(email, "@")
|
||
if n <= 0 {
|
||
return false
|
||
}
|
||
|
||
domain := strings.ToLower(email[n+1:])
|
||
|
||
for _, g := range globs {
|
||
if g.Match(domain) {
|
||
return true
|
||
}
|
||
}
|
||
|
||
return false
|
||
}
|
||
|
||
// IsAPIURL checks if URL is current Gitea instance API URL
|
||
func IsAPIURL(uri string) bool {
|
||
return strings.HasPrefix(strings.ToLower(uri), strings.ToLower(setting.AppURL+"api"))
|
||
}
|
||
|
||
// IsValidExternalURL checks if URL is valid external URL
|
||
func IsValidExternalURL(uri string) bool {
|
||
if !IsValidURL(uri) || IsAPIURL(uri) {
|
||
return false
|
||
}
|
||
|
||
u, err := url.ParseRequestURI(uri)
|
||
if err != nil {
|
||
return false
|
||
}
|
||
|
||
// Currently check only if not loopback IP is provided to keep compatibility
|
||
if isLoopbackIP(u.Hostname()) || strings.ToLower(u.Hostname()) == "localhost" {
|
||
return false
|
||
}
|
||
|
||
// TODO: Later it should be added to allow local network IP addresses
|
||
// only if allowed by special setting
|
||
|
||
return true
|
||
}
|
||
|
||
// IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers
|
||
func IsValidExternalTrackerURLFormat(uri string) bool {
|
||
if !IsValidExternalURL(uri) {
|
||
return false
|
||
}
|
||
|
||
// check for typoed variables like /{index/ or /[repo}
|
||
for _, match := range externalTrackerRegex.FindAllStringSubmatch(uri, -1) {
|
||
if (match[1] == "{" || match[2] == "}") && (match[1] != "{" || match[2] != "}") {
|
||
return false
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
var (
|
||
validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
|
||
invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars
|
||
|
||
// DevStar Studio 定制规则:判断是否是有效的 int64 ID 十进制正数字符串(UserID 或者 Repo ID)
|
||
validBase10PositiveNumberPattern = regexp.MustCompile(`^\d+$`)
|
||
)
|
||
|
||
// IsValidUsername checks if username is valid
|
||
func IsValidUsername(name string) bool {
|
||
// It is difficult to find a single pattern that is both readable and effective,
|
||
// but it's easier to use positive and negative checks.
|
||
return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
||
}
|
||
|
||
// IsValidUserIdOrRepoId 判断是否是有效的 用户ID 或者 Repo ID (十进制int64正数部分字符串校验规则)
|
||
func IsValidUserIdOrRepoId(idStr string) bool {
|
||
return validBase10PositiveNumberPattern.MatchString(idStr)
|
||
}
|