-
Notifications
You must be signed in to change notification settings - Fork 299
/
config.go
172 lines (163 loc) · 8.13 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright © 2019 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package identityserver
import (
"context"
"time"
"go.thethings.network/lorawan-stack/v3/api"
"go.thethings.network/lorawan-stack/v3/pkg/config"
"go.thethings.network/lorawan-stack/v3/pkg/email"
"go.thethings.network/lorawan-stack/v3/pkg/email/sendgrid"
"go.thethings.network/lorawan-stack/v3/pkg/email/smtp"
"go.thethings.network/lorawan-stack/v3/pkg/fetch"
"go.thethings.network/lorawan-stack/v3/pkg/oauth"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
// Config for the Identity Server
type Config struct {
DatabaseURI string `name:"database-uri" description:"Database connection URI"`
UserRegistration struct {
Invitation struct {
Required bool `name:"required" description:"Require invitations for new users"`
TokenTTL time.Duration `name:"token-ttl" description:"TTL of user invitation tokens"`
} `name:"invitation"`
ContactInfoValidation struct {
Required bool `name:"required" description:"Require contact info validation for new users"`
} `name:"contact-info-validation"`
AdminApproval struct {
Required bool `name:"required" description:"Require admin approval for new users"`
} `name:"admin-approval"`
PasswordRequirements struct {
MinLength int `name:"min-length" description:"Minimum password length"`
MaxLength int `name:"max-length" description:"Maximum password length"`
MinUppercase int `name:"min-uppercase" description:"Minimum number of uppercase letters"`
MinDigits int `name:"min-digits" description:"Minimum number of digits"`
MinSpecial int `name:"min-special" description:"Minimum number of special characters"`
} `name:"password-requirements"`
} `name:"user-registration"`
AuthCache struct {
MembershipTTL time.Duration `name:"membership-ttl" description:"TTL of membership caches"`
} `name:"auth-cache"`
OAuth oauth.Config `name:"oauth"`
ProfilePicture struct {
DisableUpload bool `name:"disable-upload" description:"Disable uploading profile pictures"`
UseGravatar bool `name:"use-gravatar" description:"Use Gravatar fallback for users without profile picture"`
Bucket string `name:"bucket" description:"Bucket used for storing profile pictures"`
BucketURL string `name:"bucket-url" description:"Base URL for public bucket access"`
} `name:"profile-picture"`
EndDevicePicture struct {
DisableUpload bool `name:"disable-upload" description:"Disable uploading end device pictures"`
Bucket string `name:"bucket" description:"Bucket used for storing end device pictures"`
BucketURL string `name:"bucket-url" description:"Base URL for public bucket access"`
} `name:"end-device-picture"`
UserRights struct {
CreateApplications bool `name:"create-applications" description:"Allow non-admin users to create applications in their user account"`
CreateClients bool `name:"create-clients" description:"Allow non-admin users to create OAuth clients in their user account"`
CreateGateways bool `name:"create-gateways" description:"Allow non-admin users to create gateways in their user account"`
CreateOrganizations bool `name:"create-organizations" description:"Allow non-admin users to create organizations in their user account"`
} `name:"user-rights"`
Email struct {
email.Config `name:",squash"`
SendGrid sendgrid.Config `name:"sendgrid"`
SMTP smtp.Config `name:"smtp"`
Templates emailTemplatesConfig `name:"templates"`
} `name:"email"`
Gateways struct {
EncryptionKeyID string `name:"encryption-key-id" description:"ID of the key used to encrypt gateway secrets at rest"`
} `name:"gateways"`
}
type emailTemplatesConfig struct {
Source string `name:"source" description:"Source of the email template files (static, directory, url, blob)"`
Static map[string][]byte `name:"-"`
Directory string `name:"directory" description:"Retrieve the email templates from the filesystem"`
URL string `name:"url" description:"Retrieve the email templates from a web server"`
Blob config.BlobPathConfig `name:"blob"`
Includes []string `name:"includes" description:"The email templates that will be preloaded on startup"`
}
// Fetcher returns a fetch.Interface based on the configuration.
// If no configuration source is set, this method returns nil, nil.
func (c emailTemplatesConfig) Fetcher(ctx context.Context, blobConf config.BlobConfig) (fetch.Interface, error) {
// TODO: Remove detection mechanism (https://github.com/TheThingsNetwork/lorawan-stack/issues/1450)
if c.Source == "" {
switch {
case c.Static != nil:
c.Source = "static"
case c.Directory != "":
c.Source = "directory"
case c.URL != "":
c.Source = "url"
case !c.Blob.IsZero():
c.Source = "blob"
}
}
switch c.Source {
case "static":
return fetch.NewMemFetcher(c.Static), nil
case "directory":
return fetch.FromFilesystem(c.Directory), nil
case "url":
return fetch.FromHTTP(c.URL, true)
case "blob":
b, err := blobConf.Bucket(ctx, c.Blob.Bucket)
if err != nil {
return nil, err
}
return fetch.FromBucket(ctx, b, c.Blob.Path), nil
default:
return nil, nil
}
}
func (c Config) toProto() *api.IsConfiguration {
return &api.IsConfiguration{
UserRegistration: &api.IsConfiguration_UserRegistration{
Invitation: &api.IsConfiguration_UserRegistration_Invitation{
Required: &wrapperspb.BoolValue{Value: c.UserRegistration.Invitation.Required},
TokenTtl: durationpb.New(c.UserRegistration.Invitation.TokenTTL),
},
ContactInfoValidation: &api.IsConfiguration_UserRegistration_ContactInfoValidation{
Required: &wrapperspb.BoolValue{Value: c.UserRegistration.ContactInfoValidation.Required},
},
AdminApproval: &api.IsConfiguration_UserRegistration_AdminApproval{
Required: &wrapperspb.BoolValue{Value: c.UserRegistration.AdminApproval.Required},
},
PasswordRequirements: &api.IsConfiguration_UserRegistration_PasswordRequirements{
MinLength: &wrapperspb.UInt32Value{Value: uint32(c.UserRegistration.PasswordRequirements.MinLength)},
MaxLength: &wrapperspb.UInt32Value{Value: uint32(c.UserRegistration.PasswordRequirements.MaxLength)},
MinUppercase: &wrapperspb.UInt32Value{Value: uint32(c.UserRegistration.PasswordRequirements.MinUppercase)},
MinDigits: &wrapperspb.UInt32Value{Value: uint32(c.UserRegistration.PasswordRequirements.MinDigits)},
MinSpecial: &wrapperspb.UInt32Value{Value: uint32(c.UserRegistration.PasswordRequirements.MinSpecial)},
},
},
ProfilePicture: &api.IsConfiguration_ProfilePicture{
DisableUpload: &wrapperspb.BoolValue{Value: c.ProfilePicture.DisableUpload},
UseGravatar: &wrapperspb.BoolValue{Value: c.ProfilePicture.UseGravatar},
},
EndDevicePicture: &api.IsConfiguration_EndDevicePicture{
DisableUpload: &wrapperspb.BoolValue{Value: c.ProfilePicture.DisableUpload},
},
UserRights: &api.IsConfiguration_UserRights{
CreateApplications: &wrapperspb.BoolValue{Value: c.UserRights.CreateApplications},
CreateClients: &wrapperspb.BoolValue{Value: c.UserRights.CreateClients},
CreateGateways: &wrapperspb.BoolValue{Value: c.UserRights.CreateGateways},
CreateOrganizations: &wrapperspb.BoolValue{Value: c.UserRights.CreateOrganizations},
},
}
}
// GetConfiguration implements the RPC that returns the configuration of the Identity Server.
func (is *IdentityServer) GetConfiguration(ctx context.Context, _ *api.GetIsConfigurationRequest) (*api.GetIsConfigurationResponse, error) {
return &api.GetIsConfigurationResponse{
Configuration: is.configFromContext(ctx).toProto(),
}, nil
}