diff --git a/conf/app.ini b/conf/app.ini index f49bdfeca..3ca64d3aa 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -190,6 +190,13 @@ ENABLE_REVERSE_PROXY_AUTHENTICATION = false ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false ; Enable captcha validation for registration ENABLE_CAPTCHA = true +; Default value for KeepEmailPrivate +; New user will get the value of this setting copied into their profile +DEFAULT_KEEP_EMAIL_PRIVATE = false +; Default value for the domain part of the user's email address in the git log +; if he has set KeepEmailPrivate true. The user's email replaced with a +; concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS. +NO_REPLY_ADDRESS = noreply.example.org [webhook] ; Hook task queue length, increase if webhook shooting starts hanging diff --git a/models/user.go b/models/user.go index 201d8c48f..e6ba2fa6f 100644 --- a/models/user.go +++ b/models/user.go @@ -75,19 +75,20 @@ type User struct { Name string `xorm:"UNIQUE NOT NULL"` FullName string // Email is the primary email address (to be used for communication) - Email string `xorm:"NOT NULL"` - Passwd string `xorm:"NOT NULL"` - LoginType LoginType - LoginSource int64 `xorm:"NOT NULL DEFAULT 0"` - LoginName string - Type UserType - OwnedOrgs []*User `xorm:"-"` - Orgs []*User `xorm:"-"` - Repos []*Repository `xorm:"-"` - Location string - Website string - Rands string `xorm:"VARCHAR(10)"` - Salt string `xorm:"VARCHAR(10)"` + Email string `xorm:"NOT NULL"` + KeepEmailPrivate bool + Passwd string `xorm:"NOT NULL"` + LoginType LoginType + LoginSource int64 `xorm:"NOT NULL DEFAULT 0"` + LoginName string + Type UserType + OwnedOrgs []*User `xorm:"-"` + Orgs []*User `xorm:"-"` + Repos []*Repository `xorm:"-"` + Location string + Website string + Rands string `xorm:"VARCHAR(10)"` + Salt string `xorm:"VARCHAR(10)"` Created time.Time `xorm:"-"` CreatedUnix int64 `xorm:"INDEX"` @@ -170,13 +171,22 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) { } } +// getEmail returns an noreply email, if the user has set to keep his +// email address private, otherwise the primary email address. +func (u *User) getEmail() string { + if u.KeepEmailPrivate { + return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress) + } + return u.Email +} + // APIFormat converts a User to api.User func (u *User) APIFormat() *api.User { return &api.User{ ID: u.ID, UserName: u.Name, FullName: u.FullName, - Email: u.Email, + Email: u.getEmail(), AvatarURL: u.AvatarLink(), } } @@ -361,7 +371,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) { func (u *User) NewGitSig() *git.Signature { return &git.Signature{ Name: u.DisplayName(), - Email: u.Email, + Email: u.getEmail(), When: time.Now(), } } @@ -616,6 +626,8 @@ func CreateUser(u *User) (err error) { return ErrEmailAlreadyUsed{u.Email} } + u.KeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate + u.LowerName = strings.ToLower(u.Name) u.AvatarEmail = u.Email u.Avatar = base.HashEmail(u.AvatarEmail) diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index f020f365d..1fa5b55c6 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -38,12 +38,14 @@ type InstallForm struct { RegisterConfirm bool MailNotify bool - OfflineMode bool - DisableGravatar bool - EnableFederatedAvatar bool - DisableRegistration bool - EnableCaptcha bool - RequireSignInView bool + OfflineMode bool + DisableGravatar bool + EnableFederatedAvatar bool + DisableRegistration bool + EnableCaptcha bool + RequireSignInView bool + DefaultKeepEmailPrivate bool + NoReplyAddress string AdminName string `binding:"OmitEmpty;AlphaDashDot;MaxSize(30)" locale:"install.admin_name"` AdminPasswd string `binding:"OmitEmpty;MaxSize(255)" locale:"install.admin_password"` @@ -97,11 +99,12 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding // UpdateProfileForm form for updating profile type UpdateProfileForm struct { - Name string `binding:"OmitEmpty;MaxSize(35)"` - FullName string `binding:"MaxSize(100)"` - Email string `binding:"Required;Email;MaxSize(254)"` - Website string `binding:"Url;MaxSize(100)"` - Location string `binding:"MaxSize(50)"` + Name string `binding:"OmitEmpty;MaxSize(35)"` + FullName string `binding:"MaxSize(100)"` + Email string `binding:"Required;Email;MaxSize(254)"` + KeepEmailPrivate bool + Website string `binding:"Url;MaxSize(100)"` + Location string `binding:"MaxSize(50)"` } // Validate valideates the fields diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 9a8a52e19..aedeb5528 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -838,6 +838,8 @@ var Service struct { EnableReverseProxyAuth bool EnableReverseProxyAutoRegister bool EnableCaptcha bool + DefaultKeepEmailPrivate bool + NoReplyAddress string } func newService() { @@ -850,6 +852,8 @@ func newService() { Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool() + Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool() + Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply.example.org") } var logLevels = map[string]string{ diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index bcb9df871..21bc1d5c7 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -124,6 +124,10 @@ save_config_failed = Fail to save configuration: %v invalid_admin_setting = Admin account setting is invalid: %v install_success = Welcome! We're glad that you chose Gitea, have fun and take care. invalid_log_root_path = Log root path is invalid: %v +default_keep_email_private = Default Value for Keep Email Private +default_keep_email_private_popup = This is the default value for the visibility of the user's email address. If set to true the email address of all new users will be hidden until the user changes his setting. +no_reply_address = No-reply Address +no_reply_address_helper = Domain for the user's email address in git logs if he keeps his email address private. E.g. user 'joe' and 'noreply.example.org' will be 'joe@noreply.example.org' [home] uname_holder = Username or email @@ -307,6 +311,8 @@ add_new_email = Add new email address add_email = Add email add_email_confirmation_sent = A new confirmation email has been sent to '%s', please check your inbox within the next %d hours to complete the confirmation process. add_email_success = Your new email address was successfully added. +keep_email_private = Keep Email Address Private +keep_email_private_popup = Your email address will be hidden from other users if this option is set. manage_ssh_keys = Manage SSH Keys add_key = Add Key @@ -1112,6 +1118,8 @@ config.disable_key_size_check = Disable Minimum Key Size Check config.enable_captcha = Enable Captcha config.active_code_lives = Active Code Lives config.reset_password_code_lives = Reset Password Code Lives +config.default_keep_email_private = Default Value for Keep Email Private +config.no_reply_address = No-reply Address config.webhook_config = Webhook Configuration config.queue_length = Queue Length diff --git a/routers/install.go b/routers/install.go index 113fd1592..080b76d4b 100644 --- a/routers/install.go +++ b/routers/install.go @@ -111,6 +111,8 @@ func Install(ctx *context.Context) { form.DisableRegistration = setting.Service.DisableRegistration form.EnableCaptcha = setting.Service.EnableCaptcha form.RequireSignInView = setting.Service.RequireSignInView + form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate + form.NoReplyAddress = setting.Service.NoReplyAddress auth.AssignForm(form, ctx.Data) ctx.HTML(200, tplInstall) @@ -291,6 +293,8 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) { cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration)) cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha)) cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView)) + cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(com.ToStr(form.DefaultKeepEmailPrivate)) + cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(com.ToStr(form.NoReplyAddress)) cfg.Section("").Key("RUN_MODE").SetValue("prod") diff --git a/routers/user/setting.go b/routers/user/setting.go index a465b0cd8..bba0f1e87 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -91,6 +91,7 @@ func SettingsPost(ctx *context.Context, form auth.UpdateProfileForm) { ctx.User.FullName = form.FullName ctx.User.Email = form.Email + ctx.User.KeepEmailPrivate = form.KeepEmailPrivate ctx.User.Website = form.Website ctx.User.Location = form.Location if err := models.UpdateUser(ctx.User); err != nil { diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 94a2a2fcc..f0c349b1d 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -119,6 +119,10 @@