Compare commits

..

12 commits
0.8.0 ... main

Author SHA1 Message Date
e327e5e2ee Fix name of message_id_domain in config example
All checks were successful
cacert-boardvoting/pipeline/head This commit looks good
2024-09-21 11:25:38 +02:00
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
20d324f5cb Fix linter error
All checks were successful
cacert-boardvoting/pipeline/head This commit looks good
- remove nextPotentialRun.Add that had no effect
2023-05-12 19:18:15 +02:00
4276594f8d Bump copyright year
Some checks failed
cacert-boardvoting/pipeline/head There was a failure building this commit
2023-05-12 17:56:45 +02:00
4a8307e16a Fix display of user 2023-05-12 17:56:17 +02:00
12796486d2 Fix summarizing vote results 2023-05-12 17:51:42 +02:00
f27f2bf801 Update to go 1.19
- update go tool in Jenkinsfile
- update go version in go.mod
- update README.md
- update dependencies
2023-05-12 17:37:04 +02:00
d0052ff3dc Import go-sqlite3 to fix test
All checks were successful
cacert-boardvoting/pipeline/head This commit looks good
2022-10-16 12:05:31 +02:00
c9d3f2a20a Fix permission issues for unauthenticated users
All checks were successful
cacert-boardvoting/pipeline/head This commit looks good
2022-10-16 11:37:51 +02:00
33 changed files with 175 additions and 1383 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:

4
Jenkinsfile vendored
View file

@ -1,6 +1,6 @@
#!groovy #!groovy
/* /*
Copyright 2017-2022 Jan Dittberner Copyright 2017-2023 Jan Dittberner
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this program except in compliance with the License. you may not use this program except in compliance with the License.
@ -18,7 +18,7 @@ pipeline {
agent any agent any
tools { tools {
go "go-1.18" go "go-1.19"
} }
environment { environment {

View file

@ -53,7 +53,7 @@ Last Changed Date: 2009-07-12 04:02:38 +0000 (Sun, 12 Jul 2009)
Local development requires Local development requires
* golang >= 1.18 * golang >= 1.19
* sqlite3 and development headers * sqlite3 and development headers
* GNU make * GNU make
* nodejs, npm and gulp (only needed if you intend to update the [jQuery] or [Fomantic-UI] CSS and JavaScript) * nodejs, npm and gulp (only needed if you intend to update the [jQuery] or [Fomantic-UI] CSS and JavaScript)

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
message_id_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

44
go.mod
View file

@ -1,46 +1,46 @@
module git.cacert.org/cacert-boardvoting module git.cacert.org/cacert-boardvoting
go 1.18 go 1.22
require ( require (
github.com/Masterminds/sprig/v3 v3.2.2 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.3.2 // indirect github.com/huandu/xstrings v1.5.0 // indirect
github.com/imdario/mergo v0.3.12 // 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.12 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.1.8 github.com/vearutop/statigz v1.4.0
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 // 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-20220216073957-c252878bcf5a github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885
github.com/alexedwards/scs/v2 v2.5.0 github.com/alexedwards/scs/v2 v2.8.0
github.com/go-chi/chi/v5 v5.0.7 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.3.7 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.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/andybalholm/brotli v1.0.4 // 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.4.1 // indirect github.com/spf13/cast v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.11.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

1364
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");
@ -199,12 +199,10 @@ func (app *Application) Routes() http.Handler {
r.Get("/newmotion/", motionHandler.NewForm) r.Get("/newmotion/", motionHandler.NewForm)
r.Post("/newmotion/", motionHandler.New) r.Post("/newmotion/", motionHandler.New)
r.Route("/motions/{tag}", func(r chi.Router) { r.Get("/motions/{tag}/edit", motionHandler.EditForm)
r.Get("/edit", motionHandler.EditForm) r.Post("/motions/{tag}/edit", motionHandler.Edit)
r.Post("/edit", motionHandler.Edit) r.Get("/motions/{tag}/withdraw", motionHandler.WithdrawForm)
r.Get("/withdraw", motionHandler.WithdrawForm) r.Post("/motions/{tag}/withdraw", motionHandler.Withdraw)
r.Post("/withdraw", motionHandler.Withdraw)
})
}) })
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {

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");
@ -33,6 +33,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
_ "github.com/mattn/go-sqlite3"
"git.cacert.org/cacert-boardvoting/internal/notifications" "git.cacert.org/cacert-boardvoting/internal/notifications"
"git.cacert.org/cacert-boardvoting/internal/models" "git.cacert.org/cacert-boardvoting/internal/models"

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");
@ -34,6 +34,10 @@ import (
) )
func checkRole(v *models.User, roles ...models.RoleName) (bool, error) { func checkRole(v *models.User, roles ...models.RoleName) (bool, error) {
if v == nil {
return false, nil
}
hasRole, err := v.HasRole(roles...) hasRole, err := v.HasRole(roles...)
if err != nil { if err != nil {
return false, fmt.Errorf("could not determine user roles: %w", err) return false, fmt.Errorf("could not determine user roles: %w", err)

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");
@ -47,7 +47,6 @@ func (r *RemindVotersJob) Schedule() {
year, month, day := now.Date() year, month, day := now.Date()
nextPotentialRun := time.Date(year, month, day+1, 0, 0, 0, 0, time.UTC) nextPotentialRun := time.Date(year, month, day+1, 0, 0, 0, 0, time.UTC)
nextPotentialRun.Add(hoursInDay * time.Hour)
relevantDue := nextPotentialRun.Add(reminderDays * hoursInDay * time.Hour) relevantDue := nextPotentialRun.Add(reminderDays * hoursInDay * time.Hour)

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-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");
@ -458,13 +458,15 @@ func sumsForDecision(ctx context.Context, tx *sqlx.Tx, d *Motion) (*VoteSums, er
return nil, fmt.Errorf("could not parse row for vote sums of motion %s: %w", d.Tag, err) return nil, fmt.Errorf("could not parse row for vote sums of motion %s: %w", d.Tag, err)
} }
switch vote { switch vote.ID {
case VoteAye: case VoteAye.ID:
sums.Ayes = count sums.Ayes = count
case VoteNaye: case VoteNaye.ID:
sums.Nayes = count sums.Nayes = count
case VoteAbstain: case VoteAbstain.ID:
sums.Abstains = count sums.Abstains = count
default:
return nil, fmt.Errorf("unknown vote type '%+v'", vote)
} }
} }
@ -605,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
} }
@ -619,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");
@ -251,6 +251,10 @@ WHERE e.address IN (?)`, emails)
} }
} }
if count == 0 {
return nil, nil
}
if user.roles, err = m.Roles(ctx, &user); err != nil { if user.roles, err = m.Roles(ctx, &user); err != nil {
return nil, fmt.Errorf("could not retrieve roles for user %s: %w", user.Name, err) return nil, fmt.Errorf("could not retrieve roles for user %s: %w", user.Name, err)
} }

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");

View file

@ -19,7 +19,7 @@
{{ with .User }} {{ with .User }}
<div class="ui label"> <div class="ui label">
<i class="id card outline icon"></i> <i class="id card outline icon"></i>
Authenticated as {{ .Name }} &lt;{{ .Reminder }}&gt; Authenticated as {{ .Name }} &lt;{{ .Reminder.String }}&gt;
</div> </div>
{{ end }} {{ end }}
</div> </div>
@ -42,7 +42,7 @@
</main> </main>
<footer class="ui vertical footer segment"> <footer class="ui vertical footer segment">
<div class="ui container"> <div class="ui container">
<span class="ui small text">© 2017-2022 CAcert Inc.</span> <span class="ui small text">© 2017-2023 CAcert Inc.</span>
</div> </div>
</footer> </footer>
</body> </body>