mirror of
https://github.com/matrix-org/dendrite.git
synced 2024-11-23 14:51:56 -06:00
Add User consent configuration
Add consentAPIMux
This commit is contained in:
parent
5106cc807c
commit
5702b84dae
|
@ -68,6 +68,31 @@ global:
|
||||||
# to other servers and the federation API will not be exposed.
|
# to other servers and the federation API will not be exposed.
|
||||||
disable_federation: false
|
disable_federation: false
|
||||||
|
|
||||||
|
# Consent tracking configuration
|
||||||
|
# If either require_at_registration or send_server_notice_to_guest are true, consent
|
||||||
|
# messages will be sent to the users.
|
||||||
|
user_consent:
|
||||||
|
# Require consent when user registers for the first time
|
||||||
|
require_at_registration: false
|
||||||
|
# The name to be shown to the user
|
||||||
|
policy_name: "Privacy policy"
|
||||||
|
# The directory to search for templates
|
||||||
|
template_dir: "./templates/privacy"
|
||||||
|
# The version of the policy. When loading templates, ".gohtml" template is added as a suffix
|
||||||
|
# e.g: ${template_dir}/1.0.gohtml needs to exist, if this is set to "1.0"
|
||||||
|
version: "1.0"
|
||||||
|
# Send a consent message to guest users
|
||||||
|
send_server_notice_to_guest: false
|
||||||
|
# Default message to send to users
|
||||||
|
server_notice_content:
|
||||||
|
msg_type: "m.text"
|
||||||
|
body: >-
|
||||||
|
Please give your consent to the privacy policy at {{ .ConsentURL }}.
|
||||||
|
# The error message to display if the user hasn't given their consent yet
|
||||||
|
block_events_error: >-
|
||||||
|
You can't send any messages until you consent to the privacy policy at
|
||||||
|
{{ .ConsentURL }}.
|
||||||
|
|
||||||
# Configuration for NATS JetStream
|
# Configuration for NATS JetStream
|
||||||
jetstream:
|
jetstream:
|
||||||
# A list of NATS Server addresses to connect to. If none are specified, an
|
# A list of NATS Server addresses to connect to. If none are specified, an
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -56,8 +57,6 @@ import (
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
userapiinthttp "github.com/matrix-org/dendrite/userapi/inthttp"
|
userapiinthttp "github.com/matrix-org/dendrite/userapi/inthttp"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
_ "net/http/pprof"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseDendrite is a base for creating new instances of dendrite. It parses
|
// BaseDendrite is a base for creating new instances of dendrite. It parses
|
||||||
|
@ -74,6 +73,7 @@ type BaseDendrite struct {
|
||||||
PublicKeyAPIMux *mux.Router
|
PublicKeyAPIMux *mux.Router
|
||||||
PublicMediaAPIMux *mux.Router
|
PublicMediaAPIMux *mux.Router
|
||||||
PublicWellKnownAPIMux *mux.Router
|
PublicWellKnownAPIMux *mux.Router
|
||||||
|
PublicConsentAPIMux *mux.Router
|
||||||
InternalAPIMux *mux.Router
|
InternalAPIMux *mux.Router
|
||||||
SynapseAdminMux *mux.Router
|
SynapseAdminMux *mux.Router
|
||||||
UseHTTPAPIs bool
|
UseHTTPAPIs bool
|
||||||
|
@ -205,6 +205,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, options ...Base
|
||||||
PublicKeyAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicKeyPathPrefix).Subrouter().UseEncodedPath(),
|
PublicKeyAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicKeyPathPrefix).Subrouter().UseEncodedPath(),
|
||||||
PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
|
PublicMediaAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicMediaPathPrefix).Subrouter().UseEncodedPath(),
|
||||||
PublicWellKnownAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicWellKnownPrefix).Subrouter().UseEncodedPath(),
|
PublicWellKnownAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.PublicWellKnownPrefix).Subrouter().UseEncodedPath(),
|
||||||
|
PublicConsentAPIMux: mux.NewRouter().SkipClean(true).PathPrefix("/_matrix").Subrouter().UseEncodedPath(),
|
||||||
InternalAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.InternalPathPrefix).Subrouter().UseEncodedPath(),
|
InternalAPIMux: mux.NewRouter().SkipClean(true).PathPrefix(httputil.InternalPathPrefix).Subrouter().UseEncodedPath(),
|
||||||
SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix("/_synapse/").Subrouter().UseEncodedPath(),
|
SynapseAdminMux: mux.NewRouter().SkipClean(true).PathPrefix("/_synapse/").Subrouter().UseEncodedPath(),
|
||||||
apiHttpClient: &apiClient,
|
apiHttpClient: &apiClient,
|
||||||
|
@ -388,6 +389,7 @@ func (b *BaseDendrite) SetupAndServeHTTP(
|
||||||
externalRouter.PathPrefix("/_synapse/").Handler(b.SynapseAdminMux)
|
externalRouter.PathPrefix("/_synapse/").Handler(b.SynapseAdminMux)
|
||||||
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.PublicMediaAPIMux)
|
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.PublicMediaAPIMux)
|
||||||
externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(b.PublicWellKnownAPIMux)
|
externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(b.PublicWellKnownAPIMux)
|
||||||
|
externalRouter.PathPrefix("/_matrix").Handler(b.PublicConsentAPIMux)
|
||||||
|
|
||||||
if internalAddr != NoListener && internalAddr != externalAddr {
|
if internalAddr != NoListener && internalAddr != externalAddr {
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
@ -57,6 +60,9 @@ type Global struct {
|
||||||
|
|
||||||
// DNS caching options for all outbound HTTP requests
|
// DNS caching options for all outbound HTTP requests
|
||||||
DNSCache DNSCacheOptions `yaml:"dns_cache"`
|
DNSCache DNSCacheOptions `yaml:"dns_cache"`
|
||||||
|
|
||||||
|
// Consent tracking options
|
||||||
|
UserConsentOptions UserConsentOptions `yaml:"user_consent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Global) Defaults(generate bool) {
|
func (c *Global) Defaults(generate bool) {
|
||||||
|
@ -72,6 +78,7 @@ func (c *Global) Defaults(generate bool) {
|
||||||
c.Metrics.Defaults(generate)
|
c.Metrics.Defaults(generate)
|
||||||
c.DNSCache.Defaults()
|
c.DNSCache.Defaults()
|
||||||
c.Sentry.Defaults()
|
c.Sentry.Defaults()
|
||||||
|
c.UserConsentOptions.Defaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
|
@ -82,6 +89,7 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
c.Metrics.Verify(configErrs, isMonolith)
|
c.Metrics.Verify(configErrs, isMonolith)
|
||||||
c.Sentry.Verify(configErrs, isMonolith)
|
c.Sentry.Verify(configErrs, isMonolith)
|
||||||
c.DNSCache.Verify(configErrs, isMonolith)
|
c.DNSCache.Verify(configErrs, isMonolith)
|
||||||
|
c.UserConsentOptions.Verify(configErrs, isMonolith)
|
||||||
}
|
}
|
||||||
|
|
||||||
type OldVerifyKeys struct {
|
type OldVerifyKeys struct {
|
||||||
|
@ -195,3 +203,71 @@ func (c *DNSCacheOptions) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
checkPositive(configErrs, "cache_size", int64(c.CacheSize))
|
checkPositive(configErrs, "cache_size", int64(c.CacheSize))
|
||||||
checkPositive(configErrs, "cache_lifetime", int64(c.CacheLifetime))
|
checkPositive(configErrs, "cache_lifetime", int64(c.CacheLifetime))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consent tracking configuration
|
||||||
|
// If either require_at_registration or send_server_notice_to_guest are true, consent
|
||||||
|
// messages will be sent to the users.
|
||||||
|
type UserConsentOptions struct {
|
||||||
|
// Require consent when user registers for the first time
|
||||||
|
RequireAtRegistration bool `yaml:"require_at_registration"`
|
||||||
|
// The name to be shown to the user
|
||||||
|
PolicyName string `yaml:"policy_name"`
|
||||||
|
// The directory to search for *.gohtml templates
|
||||||
|
TemplateDir string `yaml:"template_dir"`
|
||||||
|
// The version of the policy. When loading templates, ".gohtml" template is added as a suffix
|
||||||
|
// e.g: ${template_dir}/1.0.gohtml needs to exist, if this is set to 1.0
|
||||||
|
Version string `yaml:"version"`
|
||||||
|
// Send a consent message to guest users
|
||||||
|
SendServerNoticeToGuest bool `yaml:"send_server_notice_to_guest"`
|
||||||
|
// Default message to send to users
|
||||||
|
ServerNoticeContent struct {
|
||||||
|
MsgType string `yaml:"msg_type"`
|
||||||
|
Body string `yaml:"body"`
|
||||||
|
} `yaml:"server_notice_content"`
|
||||||
|
// The error message to display if the user hasn't given their consent yet
|
||||||
|
BlockEventsError string `yaml:"block_events_error"`
|
||||||
|
// All loaded templates
|
||||||
|
Templates *template.Template `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UserConsentOptions) Defaults() {
|
||||||
|
c.RequireAtRegistration = false
|
||||||
|
c.SendServerNoticeToGuest = false
|
||||||
|
c.PolicyName = "Privacy Policy"
|
||||||
|
c.Version = "1.0"
|
||||||
|
c.TemplateDir = "./templates/privacy"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UserConsentOptions) Verify(configErrors *ConfigErrors, isMonolith bool) {
|
||||||
|
if c.Enabled() {
|
||||||
|
checkNotEmpty(configErrors, "template_dir", c.TemplateDir)
|
||||||
|
checkNotEmpty(configErrors, "version", c.Version)
|
||||||
|
checkNotEmpty(configErrors, "policy_name", c.PolicyName)
|
||||||
|
if len(*configErrors) > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := filepath.Abs(c.TemplateDir)
|
||||||
|
if err != nil {
|
||||||
|
configErrors.Add("unable to get template directory")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read all defined *.gohtml templates
|
||||||
|
t, err := template.ParseGlob(filepath.Join(p, "*.gohtml"))
|
||||||
|
if err != nil || t == nil {
|
||||||
|
configErrors.Add(fmt.Sprintf("unable to read consent templates: %+v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Templates = t
|
||||||
|
// Verify we've got a template for the defined version
|
||||||
|
versionTemplate := c.Templates.Lookup(c.Version + ".gohtml")
|
||||||
|
if versionTemplate == nil {
|
||||||
|
configErrors.Add(fmt.Sprintf("unable to load defined '%s' policy template", c.Version))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UserConsentOptions) Enabled() bool {
|
||||||
|
return c.RequireAtRegistration || c.SendServerNoticeToGuest
|
||||||
|
}
|
||||||
|
|
|
@ -55,9 +55,9 @@ type Monolith struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAllPublicRoutes attaches all public paths to the given router
|
// AddAllPublicRoutes attaches all public paths to the given router
|
||||||
func (m *Monolith) AddAllPublicRoutes(process *process.ProcessContext, csMux, ssMux, keyMux, wkMux, mediaMux, synapseMux *mux.Router) {
|
func (m *Monolith) AddAllPublicRoutes(process *process.ProcessContext, csMux, ssMux, keyMux, wkMux, mediaMux, synapseMux, consentMux *mux.Router) {
|
||||||
clientapi.AddPublicRoutes(
|
clientapi.AddPublicRoutes(
|
||||||
csMux, synapseMux, &m.Config.ClientAPI, m.AccountDB,
|
csMux, synapseMux, consentMux, &m.Config.ClientAPI, m.AccountDB,
|
||||||
m.FedClient, m.RoomserverAPI,
|
m.FedClient, m.RoomserverAPI,
|
||||||
m.EDUInternalAPI, m.AppserviceAPI, transactions.New(),
|
m.EDUInternalAPI, m.AppserviceAPI, transactions.New(),
|
||||||
m.FederationAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider,
|
m.FederationAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider,
|
||||||
|
|
Loading…
Reference in a new issue