repo.go 13 KB

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