Compare commits

..

4 commits

Author SHA1 Message Date
39393eb612 Adapt goreleaser config for gorelease v2.0.0
All checks were successful
cacert-boardvoting/pipeline/head This commit looks good
2024-06-08 12:51:34 +02:00
a8f16192a8 Update dependencies 2024-06-08 12:51:34 +02:00
11582d3590 Update linter config and apply suggestions
- remove copyright years (they are in git)
- remove outdated linter bug workarounds
- update .golangci.yml to match current schema (as of golangci-lint 1.59.0)
2024-06-08 12:51:34 +02:00
3d16034c44 Add configurable domain part for message ids
Fixes #1
2024-06-08 12:51:14 +02:00
30 changed files with 124 additions and 1360 deletions

View file

@ -1,7 +1,9 @@
--- ---
run: run:
go: "1.17" go: "1.22"
skip-files:
issues:
exclude-files:
- boardvoting/assets.go - boardvoting/assets.go
output: output:
@ -13,7 +15,7 @@ linters-settings:
const: const:
ORGANIZATION: CAcert Inc. ORGANIZATION: CAcert Inc.
template: |- template: |-
Copyright {{ YEAR-RANGE }} {{ ORGANIZATION }} Copyright {{ ORGANIZATION }}
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -27,8 +29,8 @@ linters-settings:
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
gomnd: mnd:
ignore-functions: ignored-functions:
- 'strconv.*' - 'strconv.*'
ignored-numbers: ignored-numbers:
- '-1,0,1,2,8' - '-1,0,1,2,8'
@ -57,7 +59,7 @@ linters:
- gofmt - gofmt
- goheader - goheader
- goimports - goimports
- gomnd - mnd
- gosec - gosec
- lll - lll
- makezero - makezero

View file

@ -1,6 +1,7 @@
# This is an example .goreleaser.yml file with some sane defaults. # This is an example .goreleaser.yml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com # Make sure to check the documentation at http://goreleaser.com
project_name: cacert-boardvoting project_name: cacert-boardvoting
version: 2
before: before:
hooks: hooks:
- go mod tidy - go mod tidy
@ -17,11 +18,6 @@ builds:
- -trimpath - -trimpath
- -v - -v
main: ./cmd/boardvoting main: ./cmd/boardvoting
archives:
- replacements:
linux: Linux
amd64: x86_64
format: binary
checksum: checksum:
name_template: 'checksums.txt' name_template: 'checksums.txt'
snapshot: snapshot:

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -7,6 +7,7 @@ mail_config:
smtp_host: localhost smtp_host: localhost
smtp_port: 25 smtp_port: 25
base_url: https://motions.cacert.org base_url: https://motions.cacert.org
domain: motions.cacert.org
notice_mail_address: cacert-board@lists.cacert.org notice_mail_address: cacert-board@lists.cacert.org
vote_notice_mail_address: cacert-board-votes@lists.cacert.org vote_notice_mail_address: cacert-board-votes@lists.cacert.org
notification_sender_address: returns@cacert.org notification_sender_address: returns@cacert.org

36
go.mod
View file

@ -1,46 +1,46 @@
module git.cacert.org/cacert-boardvoting module git.cacert.org/cacert-boardvoting
go 1.19 go 1.22
require ( require (
github.com/Masterminds/sprig/v3 v3.2.3 github.com/Masterminds/sprig/v3 v3.2.3
github.com/golang-migrate/migrate/v4 v4.15.2 github.com/golang-migrate/migrate/v4 v4.17.1
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect github.com/imdario/mergo v0.3.16 // indirect
github.com/jmoiron/sqlx v1.3.5 github.com/jmoiron/sqlx v1.4.0
github.com/johejo/golang-migrate-extra v0.0.0-20211005021153-c17dd75f8b4a github.com/johejo/golang-migrate-extra v0.0.0-20211005021153-c17dd75f8b4a
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.22
github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/vearutop/statigz v1.3.0 github.com/vearutop/statigz v1.4.0
golang.org/x/crypto v0.9.0 // indirect golang.org/x/crypto v0.24.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/mail.v2 v2.3.1 gopkg.in/mail.v2 v2.3.1
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
require ( require (
github.com/alexedwards/scs/sqlite3store v0.0.0-20230327161757-10d4299e3b24 github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885
github.com/alexedwards/scs/v2 v2.5.1 github.com/alexedwards/scs/v2 v2.8.0
github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/chi/v5 v5.0.12
github.com/go-playground/form/v4 v4.2.0 github.com/go-playground/form/v4 v4.2.1
github.com/justinas/nosurf v1.1.1 github.com/justinas/nosurf v1.1.1
github.com/lestrrat-go/tcputil v0.0.0-20180223003554-d3c7f98154fb github.com/lestrrat-go/tcputil v0.0.0-20180223003554-d3c7f98154fb
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.8.3
golang.org/x/text v0.9.0 golang.org/x/text v0.16.0
) )
require ( require (
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cast v1.6.0 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

1339
go.sum

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -62,7 +62,7 @@ func Test_secureHeaders(t *testing.T) {
SecureHeaders(next).ServeHTTP(rr, r) SecureHeaders(next).ServeHTTP(rr, r)
rs := rr.Result() //nolint:bodyclose // linters bug rs := rr.Result()
defer func() { _ = rs.Body.Close() }() defer func() { _ = rs.Body.Close() }()
@ -119,7 +119,7 @@ func TestApplication_tryAuthenticate(t *testing.T) {
mw.TryAuthenticate(next).ServeHTTP(rr, r) mw.TryAuthenticate(next).ServeHTTP(rr, r)
rs := rr.Result() //nolint:bodyclose // linters bug rs := rr.Result()
defer func() { _ = rs.Body.Close() }() defer func() { _ = rs.Body.Close() }()
@ -137,7 +137,7 @@ func TestApplication_tryAuthenticate(t *testing.T) {
mw.TryAuthenticate(next).ServeHTTP(rr, r) mw.TryAuthenticate(next).ServeHTTP(rr, r)
rs := rr.Result() //nolint:bodyclose // linters bug rs := rr.Result()
defer func() { _ = rs.Body.Close() }() defer func() { _ = rs.Body.Close() }()
@ -158,11 +158,12 @@ func TestApplication_tryAuthenticate(t *testing.T) {
mw.TryAuthenticate(next).ServeHTTP(rr, r) mw.TryAuthenticate(next).ServeHTTP(rr, r)
rs := rr.Result() //nolint:bodyclose // linters bug rs := rr.Result()
defer func() { _ = rs.Body.Close() }() defer func() { _ = rs.Body.Close() }()
assert.Equal(t, http.StatusOK, rs.StatusCode) assert.Equal(t, http.StatusOK, rs.StatusCode)
user := nextCtx.Value(ctxUser) user := nextCtx.Value(ctxUser)
assert.NotNil(t, user) assert.NotNil(t, user)

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2023 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2023 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -607,12 +607,12 @@ func (m *MotionModel) List(ctx context.Context, options *MotionListOptions) ([]*
} }
func (m *MotionModel) FillVoteSums(ctx context.Context, decisions []*Motion) error { func (m *MotionModel) FillVoteSums(ctx context.Context, decisions []*Motion) error {
decisionIds := make([]int64, len(decisions)) decisionIDs := make([]int64, len(decisions))
decisionMap := make(map[int64]*Motion, len(decisions)) decisionMap := make(map[int64]*Motion, len(decisions))
for idx, decision := range decisions { for idx, decision := range decisions {
decision.Sums = &VoteSums{} decision.Sums = &VoteSums{}
decisionIds[idx] = decision.ID decisionIDs[idx] = decision.ID
decisionMap[decision.ID] = decision decisionMap[decision.ID] = decision
} }
@ -621,7 +621,7 @@ func (m *MotionModel) FillVoteSums(ctx context.Context, decisions []*Motion) err
FROM votes v FROM votes v
WHERE v.decision IN (?) WHERE v.decision IN (?)
GROUP BY v.decision, v.vote`, GROUP BY v.decision, v.vote`,
decisionIds, decisionIDs,
) )
if err != nil { if err != nil {
return fmt.Errorf("could not create IN query: %w", err) return fmt.Errorf("could not create IN query: %w", err)

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2017-2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -38,6 +38,7 @@ type MailConfig struct {
SMTPHost string `yaml:"smtp_host"` SMTPHost string `yaml:"smtp_host"`
SMTPPort int `yaml:"smtp_port"` SMTPPort int `yaml:"smtp_port"`
SMTPTimeOut time.Duration `yaml:"smtp_timeout,omitempty"` SMTPTimeOut time.Duration `yaml:"smtp_timeout,omitempty"`
Domain string `yaml:"message_id_domain"`
NotificationSenderAddress string `yaml:"notification_sender_address"` NotificationSenderAddress string `yaml:"notification_sender_address"`
NoticeMailAddress string `yaml:"notice_mail_address"` NoticeMailAddress string `yaml:"notice_mail_address"`
VoteNoticeMailAddress string `yaml:"vote_notice_mail_address"` VoteNoticeMailAddress string `yaml:"vote_notice_mail_address"`
@ -202,10 +203,10 @@ func voteNoticeRecipient(mc *MailConfig) recipientData {
} }
} }
func motionReplyHeaders(m *models.Motion) map[string][]string { func motionReplyHeaders(m *models.Motion, mc *MailConfig) map[string][]string {
return map[string][]string{ return map[string][]string{
"References": {fmt.Sprintf("<%s>", m.Tag)}, "References": {fmt.Sprintf("<%s@%s>", m.Tag, mc.Domain)},
"In-Reply-To": {fmt.Sprintf("<%s>", m.Tag)}, "In-Reply-To": {fmt.Sprintf("<%s@%s>", m.Tag, mc.Domain)},
} }
} }
@ -247,7 +248,7 @@ func (c *ClosedDecisionNotification) GetNotificationContent(mc *MailConfig) *Not
*models.Motion *models.Motion
}{Motion: c.Decision}, }{Motion: c.Decision},
subject: fmt.Sprintf("Re: %s - %s - finalized", c.Decision.Tag, c.Decision.Title), subject: fmt.Sprintf("Re: %s - %s - finalized", c.Decision.Tag, c.Decision.Title),
headers: motionReplyHeaders(c.Decision), headers: motionReplyHeaders(c.Decision, mc),
recipients: []recipientData{defaultRecipient(mc)}, recipients: []recipientData{defaultRecipient(mc)},
} }
} }
@ -275,14 +276,14 @@ func (n NewDecisionNotification) GetNotificationContent(mc *MailConfig) *Notific
UnvotedURL: unvotedURL, UnvotedURL: unvotedURL,
}, },
subject: fmt.Sprintf("%s - %s", n.Decision.Tag, n.Decision.Title), subject: fmt.Sprintf("%s - %s", n.Decision.Tag, n.Decision.Title),
headers: n.getHeaders(), headers: n.getHeaders(mc),
recipients: []recipientData{defaultRecipient(mc)}, recipients: []recipientData{defaultRecipient(mc)},
} }
} }
func (n NewDecisionNotification) getHeaders() map[string][]string { func (n NewDecisionNotification) getHeaders(mc *MailConfig) map[string][]string {
return map[string][]string{ return map[string][]string{
"Message-ID": {fmt.Sprintf("<%s>", n.Decision.Tag)}, "Message-ID": {fmt.Sprintf("<%s@%s>", n.Decision.Tag, mc.Domain)},
} }
} }
@ -309,7 +310,7 @@ func (u UpdateDecisionNotification) GetNotificationContent(mc *MailConfig) *Noti
UnvotedURL: unvotedURL, UnvotedURL: unvotedURL,
}, },
subject: fmt.Sprintf("%s - %s", u.Decision.Tag, u.Decision.Title), subject: fmt.Sprintf("%s - %s", u.Decision.Tag, u.Decision.Title),
headers: motionReplyHeaders(u.Decision), headers: motionReplyHeaders(u.Decision, mc),
recipients: []recipientData{defaultRecipient(mc)}, recipients: []recipientData{defaultRecipient(mc)},
} }
} }
@ -333,7 +334,7 @@ func (d DirectVoteNotification) GetNotificationContent(mc *MailConfig) *Notifica
Choice: d.Choice, Choice: d.Choice,
}, },
subject: fmt.Sprintf("Re: %s - %s", d.Decision.Tag, d.Decision.Title), subject: fmt.Sprintf("Re: %s - %s", d.Decision.Tag, d.Decision.Title),
headers: motionReplyHeaders(d.Decision), headers: motionReplyHeaders(d.Decision, mc),
recipients: []recipientData{voteNoticeRecipient(mc)}, recipients: []recipientData{voteNoticeRecipient(mc)},
} }
} }
@ -363,7 +364,7 @@ func (p ProxyVoteNotification) GetNotificationContent(mc *MailConfig) *Notificat
Justification: p.Justification, Justification: p.Justification,
}, },
subject: fmt.Sprintf("Re: %s - %s", p.Decision.Tag, p.Decision.Title), subject: fmt.Sprintf("Re: %s - %s", p.Decision.Tag, p.Decision.Title),
headers: motionReplyHeaders(p.Decision), headers: motionReplyHeaders(p.Decision, mc),
recipients: []recipientData{voteNoticeRecipient(mc)}, recipients: []recipientData{voteNoticeRecipient(mc)},
} }
} }
@ -381,7 +382,7 @@ func (w WithDrawMotionNotification) GetNotificationContent(mc *MailConfig) *Noti
Name string Name string
}{Motion: w.Motion, Name: w.Voter.Name}, }{Motion: w.Motion, Name: w.Voter.Name},
subject: fmt.Sprintf("Re: %s - %s", w.Motion.Tag, w.Motion.Title), subject: fmt.Sprintf("Re: %s - %s", w.Motion.Tag, w.Motion.Title),
headers: motionReplyHeaders(w.Motion), headers: motionReplyHeaders(w.Motion, mc),
recipients: []recipientData{defaultRecipient(mc)}, recipients: []recipientData{defaultRecipient(mc)},
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 CAcert Inc. Copyright CAcert Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");