Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/public-api-server/pkg/apiv1/validation.go
2499 views
1
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package apiv1
6
7
import (
8
"context"
9
"errors"
10
"fmt"
11
"strings"
12
13
connect "github.com/bufbuild/connect-go"
14
"github.com/gitpod-io/gitpod/common-go/log"
15
"github.com/gitpod-io/gitpod/common-go/namegen"
16
"github.com/google/uuid"
17
"github.com/relvacode/iso8601"
18
"google.golang.org/protobuf/proto"
19
"google.golang.org/protobuf/types/known/fieldmaskpb"
20
"google.golang.org/protobuf/types/known/timestamppb"
21
)
22
23
func validateTeamID(ctx context.Context, id string) (uuid.UUID, error) {
24
log.AddFields(ctx, log.OrganizationID(id))
25
teamID, err := validateUUID(id)
26
if err != nil {
27
return uuid.Nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("Team ID must be a valid UUID."))
28
}
29
30
return teamID, nil
31
}
32
33
func parseGitpodTimeStampOrDefault(s string) *timestamppb.Timestamp {
34
parsed, err := parseGitpodTimestamp(s)
35
if err != nil {
36
return &timestamppb.Timestamp{}
37
}
38
return parsed
39
}
40
41
func parseGitpodTimestamp(input string) (*timestamppb.Timestamp, error) {
42
parsed, err := iso8601.ParseString(input)
43
if err != nil {
44
return nil, err
45
}
46
return timestamppb.New(parsed), nil
47
}
48
49
func validateWorkspaceID(ctx context.Context, id string) (string, error) {
50
log.AddFields(ctx, log.WorkspaceID(id))
51
if id == "" {
52
return "", connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("Empty workspace id specified"))
53
}
54
55
err := namegen.ValidateWorkspaceID(id)
56
if err != nil {
57
return "", connect.NewError(connect.CodeInvalidArgument, err)
58
}
59
60
return id, nil
61
}
62
63
func validateProjectID(ctx context.Context, id string) (uuid.UUID, error) {
64
log.AddFields(ctx, log.ProjectID(id))
65
projectID, err := validateUUID(id)
66
if err != nil {
67
return uuid.Nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("Project ID must be a valid UUID."))
68
}
69
70
return projectID, nil
71
}
72
73
func validatePersonalAccessTokenID(ctx context.Context, id string) (uuid.UUID, error) {
74
log.AddFields(ctx, log.PersonalAccessTokenID(id))
75
tokenID, err := validateUUID(id)
76
if err != nil {
77
return uuid.Nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("Token ID must be a valid UUID"))
78
}
79
80
return tokenID, nil
81
}
82
83
func validateOrganizationID(ctx context.Context, id string) (uuid.UUID, error) {
84
log.AddFields(ctx, log.OrganizationID(id))
85
organizationID, err := validateUUID(id)
86
if err != nil {
87
return uuid.Nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("OrganizationID must be a valid UUID"))
88
}
89
90
return organizationID, nil
91
}
92
93
func validateOIDCClientConfigID(ctx context.Context, id string) (uuid.UUID, error) {
94
log.AddFields(ctx, log.OIDCClientConfigID(id))
95
oidcClientConfigID, err := validateUUID(id)
96
if err != nil {
97
return uuid.Nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("OIDC Client Config ID must be a valid UUID"))
98
}
99
100
return oidcClientConfigID, nil
101
}
102
103
func validateFieldMask(mask *fieldmaskpb.FieldMask, message proto.Message) (*fieldmaskpb.FieldMask, error) {
104
if mask == nil {
105
return &fieldmaskpb.FieldMask{}, nil
106
}
107
108
mask.Normalize()
109
if !mask.IsValid(message) {
110
return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("Invalid field mask specified."))
111
}
112
113
return mask, nil
114
}
115
116
func validateUUID(id string) (uuid.UUID, error) {
117
trimmed := strings.TrimSpace(id)
118
if trimmed == "" {
119
return uuid.Nil, errors.New("empty uuid")
120
}
121
122
return uuid.Parse(trimmed)
123
}
124
125