repo.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package form
  5. import (
  6. "net/url"
  7. "strings"
  8. "github.com/go-macaron/binding"
  9. "github.com/unknwon/com"
  10. "gopkg.in/macaron.v1"
  11. "gogs.io/gogs/internal/conf"
  12. "gogs.io/gogs/internal/db"
  13. "gogs.io/gogs/internal/netutil"
  14. )
  15. // _______________________________________ _________.______________________ _______________.___.
  16. // \______ \_ _____/\______ \_____ \ / _____/| \__ ___/\_____ \\______ \__ | |
  17. // | _/| __)_ | ___// | \ \_____ \ | | | | / | \| _// | |
  18. // | | \| \ | | / | \/ \| | | | / | \ | \\____ |
  19. // |____|_ /_______ / |____| \_______ /_______ /|___| |____| \_______ /____|_ // ______|
  20. // \/ \/ \/ \/ \/ \/ \/
  21. type CreateRepo struct {
  22. UserID int64 `binding:"Required"`
  23. RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
  24. Private bool
  25. Unlisted bool
  26. Description string `binding:"MaxSize(512)"`
  27. AutoInit bool
  28. Gitignores string
  29. License string
  30. Readme string
  31. }
  32. func (f *CreateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  33. return validate(errs, ctx.Data, f, ctx.Locale)
  34. }
  35. type MigrateRepo struct {
  36. CloneAddr string `json:"clone_addr" binding:"Required"`
  37. AuthUsername string `json:"auth_username"`
  38. AuthPassword string `json:"auth_password"`
  39. Uid int64 `json:"uid" binding:"Required"`
  40. RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
  41. Mirror bool `json:"mirror"`
  42. Private bool `json:"private"`
  43. Unlisted bool `json:"unlisted"`
  44. Description string `json:"description" binding:"MaxSize(512)"`
  45. }
  46. func (f *MigrateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  47. return validate(errs, ctx.Data, f, ctx.Locale)
  48. }
  49. // ParseRemoteAddr checks if given remote address is valid,
  50. // and returns composed URL with needed username and password.
  51. // It also checks if given user has permission when remote address
  52. // is actually a local path.
  53. func (f MigrateRepo) ParseRemoteAddr(user *db.User) (string, error) {
  54. remoteAddr := strings.TrimSpace(f.CloneAddr)
  55. // Remote address can be HTTP/HTTPS/Git URL or local path.
  56. if strings.HasPrefix(remoteAddr, "http://") ||
  57. strings.HasPrefix(remoteAddr, "https://") ||
  58. strings.HasPrefix(remoteAddr, "git://") {
  59. u, err := url.Parse(remoteAddr)
  60. if err != nil {
  61. return "", db.ErrInvalidCloneAddr{IsURLError: true}
  62. }
  63. if netutil.IsBlockedLocalHostname(u.Hostname(), conf.Security.LocalNetworkAllowlist) {
  64. return "", db.ErrInvalidCloneAddr{IsBlockedLocalAddress: true}
  65. }
  66. if len(f.AuthUsername)+len(f.AuthPassword) > 0 {
  67. u.User = url.UserPassword(f.AuthUsername, f.AuthPassword)
  68. }
  69. // To prevent CRLF injection in git protocol, see https://github.com/gogs/gogs/issues/6413
  70. if u.Scheme == "git" && (strings.Contains(remoteAddr, "%0d") || strings.Contains(remoteAddr, "%0a")) {
  71. return "", db.ErrInvalidCloneAddr{IsURLError: true}
  72. }
  73. remoteAddr = u.String()
  74. } else if !user.CanImportLocal() {
  75. return "", db.ErrInvalidCloneAddr{IsPermissionDenied: true}
  76. } else if !com.IsDir(remoteAddr) {
  77. return "", db.ErrInvalidCloneAddr{IsInvalidPath: true}
  78. }
  79. return remoteAddr, nil
  80. }
  81. type RepoSetting struct {
  82. RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
  83. Description string `binding:"MaxSize(512)"`
  84. Website string `binding:"Url;MaxSize(100)"`
  85. Branch string
  86. Interval int
  87. MirrorAddress string
  88. Private bool
  89. Unlisted bool
  90. EnablePrune bool
  91. // Advanced settings
  92. EnableWiki bool
  93. AllowPublicWiki bool
  94. EnableExternalWiki bool
  95. ExternalWikiURL string
  96. EnableIssues bool
  97. AllowPublicIssues bool
  98. EnableExternalTracker bool
  99. ExternalTrackerURL string
  100. TrackerURLFormat string
  101. TrackerIssueStyle string
  102. EnablePulls bool
  103. PullsIgnoreWhitespace bool
  104. PullsAllowRebase bool
  105. }
  106. func (f *RepoSetting) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  107. return validate(errs, ctx.Data, f, ctx.Locale)
  108. }
  109. // __________ .__
  110. // \______ \____________ ____ ____ | |__
  111. // | | _/\_ __ \__ \ / \_/ ___\| | \
  112. // | | \ | | \// __ \| | \ \___| Y \
  113. // |______ / |__| (____ /___| /\___ >___| /
  114. // \/ \/ \/ \/ \/
  115. type ProtectBranch struct {
  116. Protected bool
  117. RequirePullRequest bool
  118. EnableWhitelist bool
  119. WhitelistUsers string
  120. WhitelistTeams string
  121. }
  122. func (f *ProtectBranch) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  123. return validate(errs, ctx.Data, f, ctx.Locale)
  124. }
  125. // __ __ ___. .__ .__ __
  126. // / \ / \ ____\_ |__ | |__ | |__ ____ | | __
  127. // \ \/\/ // __ \| __ \| | \| | \ / _ \| |/ /
  128. // \ /\ ___/| \_\ \ Y \ Y ( <_> ) <
  129. // \__/\ / \___ >___ /___| /___| /\____/|__|_ \
  130. // \/ \/ \/ \/ \/ \/
  131. type Webhook struct {
  132. Events string
  133. Create bool
  134. Delete bool
  135. Fork bool
  136. Push bool
  137. Issues bool
  138. IssueComment bool
  139. PullRequest bool
  140. Release bool
  141. Active bool
  142. }
  143. func (f Webhook) PushOnly() bool {
  144. return f.Events == "push_only"
  145. }
  146. func (f Webhook) SendEverything() bool {
  147. return f.Events == "send_everything"
  148. }
  149. func (f Webhook) ChooseEvents() bool {
  150. return f.Events == "choose_events"
  151. }
  152. type NewWebhook struct {
  153. PayloadURL string `binding:"Required;Url"`
  154. ContentType int `binding:"Required"`
  155. Secret string
  156. Webhook
  157. }
  158. func (f *NewWebhook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  159. return validate(errs, ctx.Data, f, ctx.Locale)
  160. }
  161. type NewSlackHook struct {
  162. PayloadURL string `binding:"Required;Url"`
  163. Channel string `binding:"Required"`
  164. Username string
  165. IconURL string
  166. Color string
  167. Webhook
  168. }
  169. func (f *NewSlackHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  170. return validate(errs, ctx.Data, f, ctx.Locale)
  171. }
  172. type NewDiscordHook struct {
  173. PayloadURL string `binding:"Required;Url"`
  174. Username string
  175. IconURL string
  176. Color string
  177. Webhook
  178. }
  179. func (f *NewDiscordHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  180. return validate(errs, ctx.Data, f, ctx.Locale)
  181. }
  182. type NewDingtalkHook struct {
  183. PayloadURL string `binding:"Required;Url"`
  184. Webhook
  185. }
  186. func (f *NewDingtalkHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  187. return validate(errs, ctx.Data, f, ctx.Locale)
  188. }
  189. // .___
  190. // | | ______ ________ __ ____
  191. // | |/ ___// ___/ | \_/ __ \
  192. // | |\___ \ \___ \| | /\ ___/
  193. // |___/____ >____ >____/ \___ >
  194. // \/ \/ \/
  195. type NewIssue struct {
  196. Title string `binding:"Required;MaxSize(255)"`
  197. LabelIDs string `form:"label_ids"`
  198. MilestoneID int64
  199. AssigneeID int64
  200. Content string
  201. Files []string
  202. }
  203. func (f *NewIssue) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  204. return validate(errs, ctx.Data, f, ctx.Locale)
  205. }
  206. type CreateComment struct {
  207. Content string
  208. Status string `binding:"OmitEmpty;In(reopen,close)"`
  209. Files []string
  210. }
  211. func (f *CreateComment) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  212. return validate(errs, ctx.Data, f, ctx.Locale)
  213. }
  214. // _____ .__.__ __
  215. // / \ |__| | ____ _______/ |_ ____ ____ ____
  216. // / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
  217. // / Y \ | |_\ ___/ \___ \ | | ( <_> ) | \ ___/
  218. // \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
  219. // \/ \/ \/ \/ \/
  220. type CreateMilestone struct {
  221. Title string `binding:"Required;MaxSize(50)"`
  222. Content string
  223. Deadline string
  224. }
  225. func (f *CreateMilestone) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  226. return validate(errs, ctx.Data, f, ctx.Locale)
  227. }
  228. // .____ ___. .__
  229. // | | _____ \_ |__ ____ | |
  230. // | | \__ \ | __ \_/ __ \| |
  231. // | |___ / __ \| \_\ \ ___/| |__
  232. // |_______ (____ /___ /\___ >____/
  233. // \/ \/ \/ \/
  234. type CreateLabel struct {
  235. ID int64
  236. Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
  237. Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
  238. }
  239. func (f *CreateLabel) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  240. return validate(errs, ctx.Data, f, ctx.Locale)
  241. }
  242. type InitializeLabels struct {
  243. TemplateName string `binding:"Required"`
  244. }
  245. func (f *InitializeLabels) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  246. return validate(errs, ctx.Data, f, ctx.Locale)
  247. }
  248. // __________ .__
  249. // \______ \ ____ | | ____ _____ ______ ____
  250. // | _// __ \| | _/ __ \\__ \ / ___// __ \
  251. // | | \ ___/| |_\ ___/ / __ \_\___ \\ ___/
  252. // |____|_ /\___ >____/\___ >____ /____ >\___ >
  253. // \/ \/ \/ \/ \/ \/
  254. type NewRelease struct {
  255. TagName string `binding:"Required"`
  256. Target string `form:"tag_target" binding:"Required"`
  257. Title string `binding:"Required"`
  258. Content string
  259. Draft string
  260. Prerelease bool
  261. Files []string
  262. }
  263. func (f *NewRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  264. return validate(errs, ctx.Data, f, ctx.Locale)
  265. }
  266. type EditRelease struct {
  267. Title string `binding:"Required"`
  268. Content string
  269. Draft string
  270. Prerelease bool
  271. Files []string
  272. }
  273. func (f *EditRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  274. return validate(errs, ctx.Data, f, ctx.Locale)
  275. }
  276. // __ __.__ __ .__
  277. // / \ / \__| | _|__|
  278. // \ \/\/ / | |/ / |
  279. // \ /| | <| |
  280. // \__/\ / |__|__|_ \__|
  281. // \/ \/
  282. type NewWiki struct {
  283. OldTitle string
  284. Title string `binding:"Required"`
  285. Content string `binding:"Required"`
  286. Message string
  287. }
  288. // FIXME: use code generation to generate this method.
  289. func (f *NewWiki) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  290. return validate(errs, ctx.Data, f, ctx.Locale)
  291. }
  292. // ___________ .___.__ __
  293. // \_ _____/ __| _/|__|/ |_
  294. // | __)_ / __ | | \ __\
  295. // | \/ /_/ | | || |
  296. // /_______ /\____ | |__||__|
  297. // \/ \/
  298. type EditRepoFile struct {
  299. TreePath string `binding:"Required;MaxSize(500)"`
  300. Content string `binding:"Required"`
  301. CommitSummary string `binding:"MaxSize(100)"`
  302. CommitMessage string
  303. CommitChoice string `binding:"Required;MaxSize(50)"`
  304. NewBranchName string `binding:"AlphaDashDotSlash;MaxSize(100)"`
  305. LastCommit string
  306. }
  307. func (f *EditRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  308. return validate(errs, ctx.Data, f, ctx.Locale)
  309. }
  310. func (f *EditRepoFile) IsNewBrnach() bool {
  311. return f.CommitChoice == "commit-to-new-branch"
  312. }
  313. type EditPreviewDiff struct {
  314. Content string
  315. }
  316. func (f *EditPreviewDiff) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  317. return validate(errs, ctx.Data, f, ctx.Locale)
  318. }
  319. // ____ ___ .__ .___
  320. // | | \______ | | _________ __| _/
  321. // | | /\____ \| | / _ \__ \ / __ |
  322. // | | / | |_> > |_( <_> ) __ \_/ /_/ |
  323. // |______/ | __/|____/\____(____ /\____ |
  324. // |__| \/ \/
  325. //
  326. type UploadRepoFile struct {
  327. TreePath string `binding:"MaxSize(500)"`
  328. CommitSummary string `binding:"MaxSize(100)"`
  329. CommitMessage string
  330. CommitChoice string `binding:"Required;MaxSize(50)"`
  331. NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
  332. Files []string
  333. }
  334. func (f *UploadRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  335. return validate(errs, ctx.Data, f, ctx.Locale)
  336. }
  337. func (f *UploadRepoFile) IsNewBrnach() bool {
  338. return f.CommitChoice == "commit-to-new-branch"
  339. }
  340. type RemoveUploadFile struct {
  341. File string `binding:"Required;MaxSize(50)"`
  342. }
  343. func (f *RemoveUploadFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  344. return validate(errs, ctx.Data, f, ctx.Locale)
  345. }
  346. // ________ .__ __
  347. // \______ \ ____ | | _____/ |_ ____
  348. // | | \_/ __ \| | _/ __ \ __\/ __ \
  349. // | ` \ ___/| |_\ ___/| | \ ___/
  350. // /_______ /\___ >____/\___ >__| \___ >
  351. // \/ \/ \/ \/
  352. type DeleteRepoFile struct {
  353. CommitSummary string `binding:"MaxSize(100)"`
  354. CommitMessage string
  355. CommitChoice string `binding:"Required;MaxSize(50)"`
  356. NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
  357. }
  358. func (f *DeleteRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
  359. return validate(errs, ctx.Data, f, ctx.Locale)
  360. }
  361. func (f *DeleteRepoFile) IsNewBrnach() bool {
  362. return f.CommitChoice == "commit-to-new-branch"
  363. }