repo.go 13 KB

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