diff --git a/cmd/web.go b/cmd/web.go index d50ee62a7619..15cec05b0262 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -248,6 +248,7 @@ func runWeb(ctx *cli.Context) error { m.Combo("").Get(user.SettingsOpenID). Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost) m.Post("/delete", user.DeleteOpenID) + m.Post("/toggle_visibility", user.ToggleOpenIDVisibility) }) } diff --git a/models/fixtures/user_open_id.yml b/models/fixtures/user_open_id.yml new file mode 100644 index 000000000000..d3a367b99dfa --- /dev/null +++ b/models/fixtures/user_open_id.yml @@ -0,0 +1,17 @@ +- + id: 1 + uid: 1 + uri: https://user1.domain1.tld/ + show: false + +- + id: 2 + uid: 1 + uri: http://user1.domain2.tld/ + show: true + +- + id: 3 + uid: 2 + uri: https://domain1.tld/user2/ + show: true diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index d06a4473b834..f651a9b78756 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -98,6 +98,8 @@ var migrations = []Migration{ NewMigration("add user openid table", addUserOpenID), // v24 -> v25 NewMigration("change the key_id and primary_key_id type", changeGPGKeysColumns), + // v25 -> v26 + NewMigration("add show field in user openid table", addUserOpenIDShow), } // Migrate database to current version diff --git a/models/migrations/v25.go b/models/migrations/v25.go new file mode 100644 index 000000000000..a8d746590a46 --- /dev/null +++ b/models/migrations/v25.go @@ -0,0 +1,18 @@ +// Copyright 2017 Gitea. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "github.com/go-xorm/xorm" +) + +func addUserOpenIDShow(x *xorm.Engine) error { + if err := x.Sync2(new(UserOpenID)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/models/user_openid.go b/models/user_openid.go index a5c88e9009d7..18e847d89ddc 100644 --- a/models/user_openid.go +++ b/models/user_openid.go @@ -21,6 +21,7 @@ type UserOpenID struct { ID int64 `xorm:"pk autoincr"` UID int64 `xorm:"INDEX NOT NULL"` URI string `xorm:"UNIQUE NOT NULL"` + Show bool `xorm:"DEFAULT false"` } // GetUserOpenIDs returns all openid addresses that belongs to given user. @@ -28,6 +29,7 @@ func GetUserOpenIDs(uid int64) ([]*UserOpenID, error) { openids := make([]*UserOpenID, 0, 5) if err := x. Where("uid=?", uid). + Asc("id"). Find(&openids); err != nil { return nil, err } @@ -89,6 +91,12 @@ func DeleteUserOpenID(openid *UserOpenID) (err error) { return nil } +// ToggleUserOpenIDVisibility toggles visibility of an openid address of given user. +func ToggleUserOpenIDVisibility(id int64) (err error) { + _, err = x.Exec("update user_open_id set show = not show where id = ?", id) + return err +} + // GetUserByOpenID returns the user object by given OpenID if exists. func GetUserByOpenID(uri string) (*User, error) { if len(uri) == 0 { diff --git a/models/user_openid_test.go b/models/user_openid_test.go new file mode 100644 index 000000000000..74e3cf6f00ac --- /dev/null +++ b/models/user_openid_test.go @@ -0,0 +1,82 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetUserOpenIDs(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + + oids, err := GetUserOpenIDs(int64(1)) + if assert.NoError(t, err) { + assert.Len(t, oids, 2) + assert.Equal(t, oids[0].URI, "https://user1.domain1.tld/") + assert.False(t, oids[0].Show) + assert.Equal(t, oids[1].URI, "http://user1.domain2.tld/") + assert.True(t, oids[1].Show) + } + + oids, err = GetUserOpenIDs(int64(2)) + if assert.NoError(t, err) { + assert.Len(t, oids, 1) + assert.Equal(t, oids[0].URI, "https://domain1.tld/user2/") + assert.True(t, oids[0].Show) + } +} + +func TestGetUserByOpenID(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + + user, err := GetUserByOpenID("https://unknown") + if assert.Error(t, err) { + assert.True(t, IsErrUserNotExist(err)) + } + + user, err = GetUserByOpenID("https://user1.domain1.tld") + if assert.NoError(t, err) { + assert.Equal(t, user.ID, int64(1)) + } + + user, err = GetUserByOpenID("https://domain1.tld/user2/") + if assert.NoError(t, err) { + assert.Equal(t, user.ID, int64(2)) + } +} + +func TestToggleUserOpenIDVisibility(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + oids, err := GetUserOpenIDs(int64(2)) + if ! assert.NoError(t, err) { + return + } + assert.Len(t, oids, 1) + assert.True(t, oids[0].Show) + + err = ToggleUserOpenIDVisibility(oids[0].ID) + if ! assert.NoError(t, err) { + return + } + + oids, err = GetUserOpenIDs(int64(2)) + if assert.NoError(t, err) { + assert.Len(t, oids, 1) + assert.False(t, oids[0].Show) + } + err = ToggleUserOpenIDVisibility(oids[0].ID) + if ! assert.NoError(t, err) { + return + } + + oids, err = GetUserOpenIDs(int64(2)) + if ! assert.NoError(t, err) { + return + } + assert.Len(t, oids, 1) + assert.True(t, oids[0].Show) +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 98dfaab5d459..829c46061966 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -365,6 +365,8 @@ last_used = Last used on no_activity = No recent activity key_state_desc = This key is used in last 7 days token_state_desc = This token is used in last 7 days +show_openid = Show on profile +hide_openid = Hide from profile manage_social = Manage Associated Social Accounts social_desc = This is a list of associated social accounts. For security reasons, please make sure you recognize all of these entries, as they can be used to log in to your account. diff --git a/routers/user/profile.go b/routers/user/profile.go index 89585551ad52..eb862d6542f2 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -75,9 +75,17 @@ func Profile(ctx *context.Context) { return } + // Show OpenID URIs + openIDs, err := models.GetUserOpenIDs(ctxUser.ID) + if err != nil { + ctx.Handle(500, "GetUserOpenIDs", err) + return + } + ctx.Data["Title"] = ctxUser.DisplayName() ctx.Data["PageIsUserProfile"] = true ctx.Data["Owner"] = ctxUser + ctx.Data["OpenIDs"] = openIDs showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) orgs, err := models.GetOrgsByUserID(ctxUser.ID, showPrivate) diff --git a/routers/user/setting_openid.go b/routers/user/setting_openid.go index 5e6052d3ef4c..e33ab144ed8d 100644 --- a/routers/user/setting_openid.go +++ b/routers/user/setting_openid.go @@ -45,6 +45,12 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { ctx.Data["PageIsSettingsOpenID"] = true if ctx.HasError() { + openid, err := models.GetUserOpenIDs(ctx.User.ID) + if err != nil { + ctx.Handle(500, "GetUserOpenIDs", err) + return + } + ctx.Data["OpenIDs"] = openid ctx.HTML(200, tplSettingsOpenID) return } @@ -140,3 +146,13 @@ func DeleteOpenID(ctx *context.Context) { }) } +// ToggleOpenIDVisibility response for toggle visibility of user's openid +func ToggleOpenIDVisibility(ctx *context.Context) { + if err := models.ToggleUserOpenIDVisibility(ctx.QueryInt64("id")); err != nil { + ctx.Handle(500, "ToggleUserOpenIDVisibility", err) + return + } + + ctx.Redirect(setting.AppSubURL + "/user/settings/openid") +} + diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 08627616b5aa..a055a99a8565 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -34,6 +34,14 @@ {{.Owner.Website}} {{end}} + {{range .OpenIDs}} + {{if .Show}} +
  • + + {{.URI}} +
  • + {{end}} + {{end}}
  • {{.i18n.Tr "user.join_on"}} {{DateFmtShort .Owner.Created}}
  • diff --git a/templates/user/settings/openid.tmpl b/templates/user/settings/openid.tmpl index a8b3a4e0f5aa..9da4be427405 100644 --- a/templates/user/settings/openid.tmpl +++ b/templates/user/settings/openid.tmpl @@ -20,6 +20,24 @@ {{$.i18n.Tr "settings.delete_key"}} +
    +
    + {{$.CsrfTokenHtml}} + + {{if .Show}} + + {{else}} + + {{end}} + +
    +
    {{end}}