1// Copyright 2014 The Gogs Authors. All rights reserved.
2// Copyright 2017 The Gitea Authors. All rights reserved.
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file.
5
6package forms
7
8import (
9	"net/http"
10	"net/url"
11	"strings"
12
13	"code.gitea.io/gitea/models"
14	"code.gitea.io/gitea/modules/context"
15	"code.gitea.io/gitea/modules/setting"
16	"code.gitea.io/gitea/modules/structs"
17	"code.gitea.io/gitea/modules/web/middleware"
18	"code.gitea.io/gitea/routers/utils"
19
20	"gitea.com/go-chi/binding"
21)
22
23// _______________________________________    _________.______________________ _______________.___.
24// \______   \_   _____/\______   \_____  \  /   _____/|   \__    ___/\_____  \\______   \__  |   |
25//  |       _/|    __)_  |     ___//   |   \ \_____  \ |   | |    |    /   |   \|       _//   |   |
26//  |    |   \|        \ |    |   /    |    \/        \|   | |    |   /    |    \    |   \\____   |
27//  |____|_  /_______  / |____|   \_______  /_______  /|___| |____|   \_______  /____|_  // ______|
28//         \/        \/                   \/        \/                        \/       \/ \/
29
30// CreateRepoForm form for creating repository
31type CreateRepoForm struct {
32	UID           int64  `binding:"Required"`
33	RepoName      string `binding:"Required;AlphaDashDot;MaxSize(100)"`
34	Private       bool
35	Description   string `binding:"MaxSize(255)"`
36	DefaultBranch string `binding:"GitRefName;MaxSize(100)"`
37	AutoInit      bool
38	Gitignores    string
39	IssueLabels   string
40	License       string
41	Readme        string
42	Template      bool
43
44	RepoTemplate int64
45	GitContent   bool
46	Topics       bool
47	GitHooks     bool
48	Webhooks     bool
49	Avatar       bool
50	Labels       bool
51	TrustModel   string
52}
53
54// Validate validates the fields
55func (f *CreateRepoForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
56	ctx := context.GetContext(req)
57	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
58}
59
60// MigrateRepoForm form for migrating repository
61// this is used to interact with web ui
62type MigrateRepoForm struct {
63	// required: true
64	CloneAddr    string                 `json:"clone_addr" binding:"Required"`
65	Service      structs.GitServiceType `json:"service"`
66	AuthUsername string                 `json:"auth_username"`
67	AuthPassword string                 `json:"auth_password"`
68	AuthToken    string                 `json:"auth_token"`
69	// required: true
70	UID int64 `json:"uid" binding:"Required"`
71	// required: true
72	RepoName       string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
73	Mirror         bool   `json:"mirror"`
74	LFS            bool   `json:"lfs"`
75	LFSEndpoint    string `json:"lfs_endpoint"`
76	Private        bool   `json:"private"`
77	Description    string `json:"description" binding:"MaxSize(255)"`
78	Wiki           bool   `json:"wiki"`
79	Milestones     bool   `json:"milestones"`
80	Labels         bool   `json:"labels"`
81	Issues         bool   `json:"issues"`
82	PullRequests   bool   `json:"pull_requests"`
83	Releases       bool   `json:"releases"`
84	MirrorInterval string `json:"mirror_interval"`
85}
86
87// Validate validates the fields
88func (f *MigrateRepoForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
89	ctx := context.GetContext(req)
90	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
91}
92
93// ParseRemoteAddr checks if given remote address is valid,
94// and returns composed URL with needed username and password.
95func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, error) {
96	remoteAddr = strings.TrimSpace(remoteAddr)
97	// Remote address can be HTTP/HTTPS/Git URL or local path.
98	if strings.HasPrefix(remoteAddr, "http://") ||
99		strings.HasPrefix(remoteAddr, "https://") ||
100		strings.HasPrefix(remoteAddr, "git://") {
101		u, err := url.Parse(remoteAddr)
102		if err != nil {
103			return "", &models.ErrInvalidCloneAddr{IsURLError: true}
104		}
105		if len(authUsername)+len(authPassword) > 0 {
106			u.User = url.UserPassword(authUsername, authPassword)
107		}
108		remoteAddr = u.String()
109	}
110
111	return remoteAddr, nil
112}
113
114// RepoSettingForm form for changing repository settings
115type RepoSettingForm struct {
116	RepoName           string `binding:"Required;AlphaDashDot;MaxSize(100)"`
117	Description        string `binding:"MaxSize(255)"`
118	Website            string `binding:"ValidUrl;MaxSize(255)"`
119	Interval           string
120	MirrorAddress      string
121	MirrorUsername     string
122	MirrorPassword     string
123	LFS                bool   `form:"mirror_lfs"`
124	LFSEndpoint        string `form:"mirror_lfs_endpoint"`
125	PushMirrorID       string
126	PushMirrorAddress  string
127	PushMirrorUsername string
128	PushMirrorPassword string
129	PushMirrorInterval string
130	Private            bool
131	Template           bool
132	EnablePrune        bool
133
134	// Advanced settings
135	EnableWiki                            bool
136	EnableExternalWiki                    bool
137	ExternalWikiURL                       string
138	EnableIssues                          bool
139	EnableExternalTracker                 bool
140	ExternalTrackerURL                    string
141	TrackerURLFormat                      string
142	TrackerIssueStyle                     string
143	EnableCloseIssuesViaCommitInAnyBranch bool
144	EnableProjects                        bool
145	EnablePulls                           bool
146	PullsIgnoreWhitespace                 bool
147	PullsAllowMerge                       bool
148	PullsAllowRebase                      bool
149	PullsAllowRebaseMerge                 bool
150	PullsAllowSquash                      bool
151	PullsAllowManualMerge                 bool
152	PullsDefaultMergeStyle                string
153	EnableAutodetectManualMerge           bool
154	DefaultDeleteBranchAfterMerge         bool
155	EnableTimetracker                     bool
156	AllowOnlyContributorsToTrackTime      bool
157	EnableIssueDependencies               bool
158	IsArchived                            bool
159
160	// Signing Settings
161	TrustModel string
162
163	// Admin settings
164	EnableHealthCheck  bool
165	RequestReindexType string
166}
167
168// Validate validates the fields
169func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
170	ctx := context.GetContext(req)
171	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
172}
173
174// __________                             .__
175// \______   \____________    ____   ____ |  |__
176//  |    |  _/\_  __ \__  \  /    \_/ ___\|  |  \
177//  |    |   \ |  | \// __ \|   |  \  \___|   Y  \
178//  |______  / |__|  (____  /___|  /\___  >___|  /
179//         \/             \/     \/     \/     \/
180
181// ProtectBranchForm form for changing protected branch settings
182type ProtectBranchForm struct {
183	Protected                     bool
184	EnablePush                    string
185	WhitelistUsers                string
186	WhitelistTeams                string
187	WhitelistDeployKeys           bool
188	EnableMergeWhitelist          bool
189	MergeWhitelistUsers           string
190	MergeWhitelistTeams           string
191	EnableStatusCheck             bool
192	StatusCheckContexts           []string
193	RequiredApprovals             int64
194	EnableApprovalsWhitelist      bool
195	ApprovalsWhitelistUsers       string
196	ApprovalsWhitelistTeams       string
197	BlockOnRejectedReviews        bool
198	BlockOnOfficialReviewRequests bool
199	BlockOnOutdatedBranch         bool
200	DismissStaleApprovals         bool
201	RequireSignedCommits          bool
202	ProtectedFilePatterns         string
203	UnprotectedFilePatterns       string
204}
205
206// Validate validates the fields
207func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
208	ctx := context.GetContext(req)
209	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
210}
211
212//  __      __      ___.   .__    .__            __
213// /  \    /  \ ____\_ |__ |  |__ |  |__   ____ |  | __
214// \   \/\/   // __ \| __ \|  |  \|  |  \ /  _ \|  |/ /
215//  \        /\  ___/| \_\ \   Y  \   Y  (  <_> )    <
216//   \__/\  /  \___  >___  /___|  /___|  /\____/|__|_ \
217//        \/       \/    \/     \/     \/            \/
218
219// WebhookForm form for changing web hook
220type WebhookForm struct {
221	Events               string
222	Create               bool
223	Delete               bool
224	Fork                 bool
225	Issues               bool
226	IssueAssign          bool
227	IssueLabel           bool
228	IssueMilestone       bool
229	IssueComment         bool
230	Release              bool
231	Push                 bool
232	PullRequest          bool
233	PullRequestAssign    bool
234	PullRequestLabel     bool
235	PullRequestMilestone bool
236	PullRequestComment   bool
237	PullRequestReview    bool
238	PullRequestSync      bool
239	Repository           bool
240	Active               bool
241	BranchFilter         string `binding:"GlobPattern"`
242}
243
244// PushOnly if the hook will be triggered when push
245func (f WebhookForm) PushOnly() bool {
246	return f.Events == "push_only"
247}
248
249// SendEverything if the hook will be triggered any event
250func (f WebhookForm) SendEverything() bool {
251	return f.Events == "send_everything"
252}
253
254// ChooseEvents if the hook will be triggered choose events
255func (f WebhookForm) ChooseEvents() bool {
256	return f.Events == "choose_events"
257}
258
259// NewWebhookForm form for creating web hook
260type NewWebhookForm struct {
261	PayloadURL  string `binding:"Required;ValidUrl"`
262	HTTPMethod  string `binding:"Required;In(POST,GET)"`
263	ContentType int    `binding:"Required"`
264	Secret      string
265	WebhookForm
266}
267
268// Validate validates the fields
269func (f *NewWebhookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
270	ctx := context.GetContext(req)
271	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
272}
273
274// NewGogshookForm form for creating gogs hook
275type NewGogshookForm struct {
276	PayloadURL  string `binding:"Required;ValidUrl"`
277	ContentType int    `binding:"Required"`
278	Secret      string
279	WebhookForm
280}
281
282// Validate validates the fields
283func (f *NewGogshookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
284	ctx := context.GetContext(req)
285	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
286}
287
288// NewSlackHookForm form for creating slack hook
289type NewSlackHookForm struct {
290	PayloadURL string `binding:"Required;ValidUrl"`
291	Channel    string `binding:"Required"`
292	Username   string
293	IconURL    string
294	Color      string
295	WebhookForm
296}
297
298// Validate validates the fields
299func (f *NewSlackHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
300	ctx := context.GetContext(req)
301	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
302}
303
304// HasInvalidChannel validates the channel name is in the right format
305func (f NewSlackHookForm) HasInvalidChannel() bool {
306	return !utils.IsValidSlackChannel(f.Channel)
307}
308
309// NewDiscordHookForm form for creating discord hook
310type NewDiscordHookForm struct {
311	PayloadURL string `binding:"Required;ValidUrl"`
312	Username   string
313	IconURL    string
314	WebhookForm
315}
316
317// Validate validates the fields
318func (f *NewDiscordHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
319	ctx := context.GetContext(req)
320	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
321}
322
323// NewDingtalkHookForm form for creating dingtalk hook
324type NewDingtalkHookForm struct {
325	PayloadURL string `binding:"Required;ValidUrl"`
326	WebhookForm
327}
328
329// Validate validates the fields
330func (f *NewDingtalkHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
331	ctx := context.GetContext(req)
332	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
333}
334
335// NewTelegramHookForm form for creating telegram hook
336type NewTelegramHookForm struct {
337	BotToken string `binding:"Required"`
338	ChatID   string `binding:"Required"`
339	WebhookForm
340}
341
342// Validate validates the fields
343func (f *NewTelegramHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
344	ctx := context.GetContext(req)
345	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
346}
347
348// NewMatrixHookForm form for creating Matrix hook
349type NewMatrixHookForm struct {
350	HomeserverURL string `binding:"Required;ValidUrl"`
351	RoomID        string `binding:"Required"`
352	AccessToken   string `binding:"Required"`
353	MessageType   int
354	WebhookForm
355}
356
357// Validate validates the fields
358func (f *NewMatrixHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
359	ctx := context.GetContext(req)
360	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
361}
362
363// NewMSTeamsHookForm form for creating MS Teams hook
364type NewMSTeamsHookForm struct {
365	PayloadURL string `binding:"Required;ValidUrl"`
366	WebhookForm
367}
368
369// Validate validates the fields
370func (f *NewMSTeamsHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
371	ctx := context.GetContext(req)
372	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
373}
374
375// NewFeishuHookForm form for creating feishu hook
376type NewFeishuHookForm struct {
377	PayloadURL string `binding:"Required;ValidUrl"`
378	WebhookForm
379}
380
381// Validate validates the fields
382func (f *NewFeishuHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
383	ctx := context.GetContext(req)
384	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
385}
386
387// NewWechatWorkHookForm form for creating wechatwork hook
388type NewWechatWorkHookForm struct {
389	PayloadURL string `binding:"Required;ValidUrl"`
390	WebhookForm
391}
392
393// Validate validates the fields
394func (f *NewWechatWorkHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
395	ctx := context.GetContext(req)
396	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
397}
398
399// .___
400// |   | ______ ________ __   ____
401// |   |/  ___//  ___/  |  \_/ __ \
402// |   |\___ \ \___ \|  |  /\  ___/
403// |___/____  >____  >____/  \___  >
404//          \/     \/            \/
405
406// CreateIssueForm form for creating issue
407type CreateIssueForm struct {
408	Title       string `binding:"Required;MaxSize(255)"`
409	LabelIDs    string `form:"label_ids"`
410	AssigneeIDs string `form:"assignee_ids"`
411	Ref         string `form:"ref"`
412	MilestoneID int64
413	ProjectID   int64
414	AssigneeID  int64
415	Content     string
416	Files       []string
417}
418
419// Validate validates the fields
420func (f *CreateIssueForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
421	ctx := context.GetContext(req)
422	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
423}
424
425// CreateCommentForm form for creating comment
426type CreateCommentForm struct {
427	Content string
428	Status  string `binding:"OmitEmpty;In(reopen,close)"`
429	Files   []string
430}
431
432// Validate validates the fields
433func (f *CreateCommentForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
434	ctx := context.GetContext(req)
435	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
436}
437
438// ReactionForm form for adding and removing reaction
439type ReactionForm struct {
440	Content string `binding:"Required"`
441}
442
443// Validate validates the fields
444func (f *ReactionForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
445	ctx := context.GetContext(req)
446	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
447}
448
449// IssueLockForm form for locking an issue
450type IssueLockForm struct {
451	Reason string `binding:"Required"`
452}
453
454// Validate validates the fields
455func (i *IssueLockForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
456	ctx := context.GetContext(req)
457	return middleware.Validate(errs, ctx.Data, i, ctx.Locale)
458}
459
460// HasValidReason checks to make sure that the reason submitted in
461// the form matches any of the values in the config
462func (i IssueLockForm) HasValidReason() bool {
463	if strings.TrimSpace(i.Reason) == "" {
464		return true
465	}
466
467	for _, v := range setting.Repository.Issue.LockReasons {
468		if v == i.Reason {
469			return true
470		}
471	}
472
473	return false
474}
475
476// __________                   __               __
477// \______   \_______  ____    |__| ____   _____/  |_  ______
478//  |     ___/\_  __ \/  _ \   |  |/ __ \_/ ___\   __\/  ___/
479//  |    |     |  | \(  <_> )  |  \  ___/\  \___|  |  \___ \
480//  |____|     |__|   \____/\__|  |\___  >\___  >__| /____  >
481//                         \______|    \/     \/          \/
482
483// CreateProjectForm form for creating a project
484type CreateProjectForm struct {
485	Title     string `binding:"Required;MaxSize(100)"`
486	Content   string
487	BoardType models.ProjectBoardType
488}
489
490// UserCreateProjectForm is a from for creating an individual or organization
491// form.
492type UserCreateProjectForm struct {
493	Title     string `binding:"Required;MaxSize(100)"`
494	Content   string
495	BoardType models.ProjectBoardType
496	UID       int64 `binding:"Required"`
497}
498
499// EditProjectBoardForm is a form for editing a project board
500type EditProjectBoardForm struct {
501	Title   string `binding:"Required;MaxSize(100)"`
502	Sorting int8
503	Color   string `binding:"MaxSize(7)"`
504}
505
506//    _____  .__.__                   __
507//   /     \ |__|  |   ____   _______/  |_  ____   ____   ____
508//  /  \ /  \|  |  | _/ __ \ /  ___/\   __\/  _ \ /    \_/ __ \
509// /    Y    \  |  |_\  ___/ \___ \  |  | (  <_> )   |  \  ___/
510// \____|__  /__|____/\___  >____  > |__|  \____/|___|  /\___  >
511//         \/             \/     \/                   \/     \/
512
513// CreateMilestoneForm form for creating milestone
514type CreateMilestoneForm struct {
515	Title    string `binding:"Required;MaxSize(50)"`
516	Content  string
517	Deadline string
518}
519
520// Validate validates the fields
521func (f *CreateMilestoneForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
522	ctx := context.GetContext(req)
523	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
524}
525
526// .____          ___.          .__
527// |    |   _____ \_ |__   ____ |  |
528// |    |   \__  \ | __ \_/ __ \|  |
529// |    |___ / __ \| \_\ \  ___/|  |__
530// |_______ (____  /___  /\___  >____/
531//         \/    \/    \/     \/
532
533// CreateLabelForm form for creating label
534type CreateLabelForm struct {
535	ID          int64
536	Title       string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
537	Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
538	Color       string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
539}
540
541// Validate validates the fields
542func (f *CreateLabelForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
543	ctx := context.GetContext(req)
544	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
545}
546
547// InitializeLabelsForm form for initializing labels
548type InitializeLabelsForm struct {
549	TemplateName string `binding:"Required"`
550}
551
552// Validate validates the fields
553func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
554	ctx := context.GetContext(req)
555	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
556}
557
558// __________      .__  .__    __________                                     __
559// \______   \__ __|  | |  |   \______   \ ____  ________ __   ____   _______/  |_
560//  |     ___/  |  \  | |  |    |       _// __ \/ ____/  |  \_/ __ \ /  ___/\   __\
561//  |    |   |  |  /  |_|  |__  |    |   \  ___< <_|  |  |  /\  ___/ \___ \  |  |
562//  |____|   |____/|____/____/  |____|_  /\___  >__   |____/  \___  >____  > |__|
563//                                     \/     \/   |__|           \/     \/
564
565// MergePullRequestForm form for merging Pull Request
566// swagger:model MergePullRequestOption
567type MergePullRequestForm struct {
568	// required: true
569	// enum: merge,rebase,rebase-merge,squash,manually-merged
570	Do                     string `binding:"Required;In(merge,rebase,rebase-merge,squash,manually-merged)"`
571	MergeTitleField        string
572	MergeMessageField      string
573	MergeCommitID          string // only used for manually-merged
574	HeadCommitID           string `json:"head_commit_id,omitempty"`
575	ForceMerge             *bool  `json:"force_merge,omitempty"`
576	DeleteBranchAfterMerge bool   `json:"delete_branch_after_merge,omitempty"`
577}
578
579// Validate validates the fields
580func (f *MergePullRequestForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
581	ctx := context.GetContext(req)
582	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
583}
584
585// CodeCommentForm form for adding code comments for PRs
586type CodeCommentForm struct {
587	Origin         string `binding:"Required;In(timeline,diff)"`
588	Content        string `binding:"Required"`
589	Side           string `binding:"Required;In(previous,proposed)"`
590	Line           int64
591	TreePath       string `form:"path" binding:"Required"`
592	IsReview       bool   `form:"is_review"`
593	Reply          int64  `form:"reply"`
594	LatestCommitID string
595}
596
597// Validate validates the fields
598func (f *CodeCommentForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
599	ctx := context.GetContext(req)
600	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
601}
602
603// SubmitReviewForm for submitting a finished code review
604type SubmitReviewForm struct {
605	Content  string
606	Type     string `binding:"Required;In(approve,comment,reject)"`
607	CommitID string
608	Files    []string
609}
610
611// Validate validates the fields
612func (f *SubmitReviewForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
613	ctx := context.GetContext(req)
614	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
615}
616
617// ReviewType will return the corresponding reviewtype for type
618func (f SubmitReviewForm) ReviewType() models.ReviewType {
619	switch f.Type {
620	case "approve":
621		return models.ReviewTypeApprove
622	case "comment":
623		return models.ReviewTypeComment
624	case "reject":
625		return models.ReviewTypeReject
626	default:
627		return models.ReviewTypeUnknown
628	}
629}
630
631// HasEmptyContent checks if the content of the review form is empty.
632func (f SubmitReviewForm) HasEmptyContent() bool {
633	reviewType := f.ReviewType()
634
635	return (reviewType == models.ReviewTypeComment || reviewType == models.ReviewTypeReject) &&
636		len(strings.TrimSpace(f.Content)) == 0
637}
638
639// DismissReviewForm for dismissing stale review by repo admin
640type DismissReviewForm struct {
641	ReviewID int64 `binding:"Required"`
642	Message  string
643}
644
645// __________       .__
646// \______   \ ____ |  |   ____ _____    ______ ____
647//  |       _// __ \|  | _/ __ \\__  \  /  ___// __ \
648//  |    |   \  ___/|  |_\  ___/ / __ \_\___ \\  ___/
649//  |____|_  /\___  >____/\___  >____  /____  >\___  >
650//         \/     \/          \/     \/     \/     \/
651
652// NewReleaseForm form for creating release
653type NewReleaseForm struct {
654	TagName    string `binding:"Required;GitRefName;MaxSize(255)"`
655	Target     string `form:"tag_target" binding:"Required;MaxSize(255)"`
656	Title      string `binding:"Required;MaxSize(255)"`
657	Content    string
658	Draft      string
659	TagOnly    string
660	Prerelease bool
661	AddTagMsg  bool
662	Files      []string
663}
664
665// Validate validates the fields
666func (f *NewReleaseForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
667	ctx := context.GetContext(req)
668	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
669}
670
671// EditReleaseForm form for changing release
672type EditReleaseForm struct {
673	Title      string `form:"title" binding:"Required;MaxSize(255)"`
674	Content    string `form:"content"`
675	Draft      string `form:"draft"`
676	Prerelease bool   `form:"prerelease"`
677	Files      []string
678}
679
680// Validate validates the fields
681func (f *EditReleaseForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
682	ctx := context.GetContext(req)
683	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
684}
685
686//  __      __.__ __   .__
687// /  \    /  \__|  | _|__|
688// \   \/\/   /  |  |/ /  |
689//  \        /|  |    <|  |
690//   \__/\  / |__|__|_ \__|
691//        \/          \/
692
693// NewWikiForm form for creating wiki
694type NewWikiForm struct {
695	Title   string `binding:"Required"`
696	Content string `binding:"Required"`
697	Message string
698}
699
700// Validate validates the fields
701// FIXME: use code generation to generate this method.
702func (f *NewWikiForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
703	ctx := context.GetContext(req)
704	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
705}
706
707// ___________    .___.__  __
708// \_   _____/  __| _/|__|/  |_
709//  |    __)_  / __ | |  \   __\
710//  |        \/ /_/ | |  ||  |
711// /_______  /\____ | |__||__|
712//         \/      \/
713
714// EditRepoFileForm form for changing repository file
715type EditRepoFileForm struct {
716	TreePath      string `binding:"Required;MaxSize(500)"`
717	Content       string
718	CommitSummary string `binding:"MaxSize(100)"`
719	CommitMessage string
720	CommitChoice  string `binding:"Required;MaxSize(50)"`
721	NewBranchName string `binding:"GitRefName;MaxSize(100)"`
722	LastCommit    string
723	Signoff       bool
724}
725
726// Validate validates the fields
727func (f *EditRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
728	ctx := context.GetContext(req)
729	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
730}
731
732// EditPreviewDiffForm form for changing preview diff
733type EditPreviewDiffForm struct {
734	Content string
735}
736
737// Validate validates the fields
738func (f *EditPreviewDiffForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
739	ctx := context.GetContext(req)
740	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
741}
742
743//  ____ ___        .__                    .___
744// |    |   \______ |  |   _________     __| _/
745// |    |   /\____ \|  |  /  _ \__  \   / __ |
746// |    |  / |  |_> >  |_(  <_> ) __ \_/ /_/ |
747// |______/  |   __/|____/\____(____  /\____ |
748//           |__|                   \/      \/
749//
750
751// UploadRepoFileForm form for uploading repository file
752type UploadRepoFileForm struct {
753	TreePath      string `binding:"MaxSize(500)"`
754	CommitSummary string `binding:"MaxSize(100)"`
755	CommitMessage string
756	CommitChoice  string `binding:"Required;MaxSize(50)"`
757	NewBranchName string `binding:"GitRefName;MaxSize(100)"`
758	Files         []string
759	Signoff       bool
760}
761
762// Validate validates the fields
763func (f *UploadRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
764	ctx := context.GetContext(req)
765	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
766}
767
768// RemoveUploadFileForm form for removing uploaded file
769type RemoveUploadFileForm struct {
770	File string `binding:"Required;MaxSize(50)"`
771}
772
773// Validate validates the fields
774func (f *RemoveUploadFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
775	ctx := context.GetContext(req)
776	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
777}
778
779// ________         .__          __
780// \______ \   ____ |  |   _____/  |_  ____
781// |    |  \_/ __ \|  | _/ __ \   __\/ __ \
782// |    `   \  ___/|  |_\  ___/|  | \  ___/
783// /_______  /\___  >____/\___  >__|  \___  >
784//         \/     \/          \/          \/
785
786// DeleteRepoFileForm form for deleting repository file
787type DeleteRepoFileForm struct {
788	CommitSummary string `binding:"MaxSize(100)"`
789	CommitMessage string
790	CommitChoice  string `binding:"Required;MaxSize(50)"`
791	NewBranchName string `binding:"GitRefName;MaxSize(100)"`
792	LastCommit    string
793	Signoff       bool
794}
795
796// Validate validates the fields
797func (f *DeleteRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
798	ctx := context.GetContext(req)
799	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
800}
801
802// ___________.__                 ___________                     __
803// \__    ___/|__| _____   ____   \__    ___/___________    ____ |  | __ ___________
804// |    |   |  |/     \_/ __ \    |    |  \_  __ \__  \ _/ ___\|  |/ // __ \_  __ \
805// |    |   |  |  Y Y  \  ___/    |    |   |  | \// __ \\  \___|    <\  ___/|  | \/
806// |____|   |__|__|_|  /\___  >   |____|   |__|  (____  /\___  >__|_ \\___  >__|
807// \/     \/                        \/     \/     \/    \/
808
809// AddTimeManuallyForm form that adds spent time manually.
810type AddTimeManuallyForm struct {
811	Hours   int `binding:"Range(0,1000)"`
812	Minutes int `binding:"Range(0,1000)"`
813}
814
815// Validate validates the fields
816func (f *AddTimeManuallyForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
817	ctx := context.GetContext(req)
818	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
819}
820
821// SaveTopicForm form for save topics for repository
822type SaveTopicForm struct {
823	Topics []string `binding:"topics;Required;"`
824}
825
826// DeadlineForm hold the validation rules for deadlines
827type DeadlineForm struct {
828	DateString string `form:"date" binding:"Required;Size(10)"`
829}
830
831// Validate validates the fields
832func (f *DeadlineForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
833	ctx := context.GetContext(req)
834	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
835}
836