repo.go 13 KB

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