summaryrefslogtreecommitdiffstats
path: root/models/user.go
diff options
context:
space:
mode:
authorSergey Dryabzhinsky <sergey@rusoft.ru>2021-06-26 22:53:14 +0300
committerGitHub <noreply@github.com>2021-06-26 20:53:14 +0100
commit22a0636544237bcffb46b36b593a501e77ae02cc (patch)
tree009c2bcf2b478f45356b8aae59f29091ffc5809f /models/user.go
parent19ac575d572af655ab691f829d0b4de38a1f10be (diff)
downloadgitea-22a0636544237bcffb46b36b593a501e77ae02cc.tar.gz
gitea-22a0636544237bcffb46b36b593a501e77ae02cc.zip
Add Visible modes function from Organisation to Users too (#16069)
You can limit or hide organisations. This pull make it also posible for users - new strings to translte - add checkbox to user profile form - add checkbox to admin user.edit form - filter explore page user search - filter api admin and public user searches - allow admins view "hidden" users - add app option DEFAULT_USER_VISIBILITY - rewrite many files to use Visibility field - check for teams intersection - fix context output - right fake 404 if not visible Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'models/user.go')
-rw-r--r--models/user.go105
1 files changed, 91 insertions, 14 deletions
diff --git a/models/user.go b/models/user.go
index 5998341422..221c840a7f 100644
--- a/models/user.go
+++ b/models/user.go
@@ -432,6 +432,62 @@ func (u *User) IsPasswordSet() bool {
return len(u.Passwd) != 0
}
+// IsVisibleToUser check if viewer is able to see user profile
+func (u *User) IsVisibleToUser(viewer *User) bool {
+ return u.isVisibleToUser(x, viewer)
+}
+
+func (u *User) isVisibleToUser(e Engine, viewer *User) bool {
+ if viewer != nil && viewer.IsAdmin {
+ return true
+ }
+
+ switch u.Visibility {
+ case structs.VisibleTypePublic:
+ return true
+ case structs.VisibleTypeLimited:
+ if viewer == nil || viewer.IsRestricted {
+ return false
+ }
+ return true
+ case structs.VisibleTypePrivate:
+ if viewer == nil || viewer.IsRestricted {
+ return false
+ }
+
+ // If they follow - they see each over
+ follower := IsFollowing(u.ID, viewer.ID)
+ if follower {
+ return true
+ }
+
+ // Now we need to check if they in some organization together
+ count, err := x.Table("team_user").
+ Where(
+ builder.And(
+ builder.Eq{"uid": viewer.ID},
+ builder.Or(
+ builder.Eq{"org_id": u.ID},
+ builder.In("org_id",
+ builder.Select("org_id").
+ From("team_user", "t2").
+ Where(builder.Eq{"uid": u.ID}))))).
+ Count(new(TeamUser))
+ if err != nil {
+ return false
+ }
+
+ if count < 0 {
+ // No common organization
+ return false
+ }
+
+ // they are in an organization together
+ return true
+ }
+ return false
+}
+
// IsOrganization returns true if user is actually a organization.
func (u *User) IsOrganization() bool {
return u.Type == UserTypeOrganization
@@ -796,8 +852,13 @@ func IsUsableUsername(name string) error {
return isUsableName(reservedUsernames, reservedUserPatterns, name)
}
+// CreateUserOverwriteOptions are an optional options who overwrite system defaults on user creation
+type CreateUserOverwriteOptions struct {
+ Visibility structs.VisibleType
+}
+
// CreateUser creates record of a new user.
-func CreateUser(u *User) (err error) {
+func CreateUser(u *User, overwriteDefault ...*CreateUserOverwriteOptions) (err error) {
if err = IsUsableUsername(u.Name); err != nil {
return err
}
@@ -831,8 +892,6 @@ 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
if u.Rands, err = GetUserSalt(); err != nil {
@@ -841,10 +900,18 @@ func CreateUser(u *User) (err error) {
if err = u.SetPassword(u.Passwd); err != nil {
return err
}
+
+ // set system defaults
+ u.KeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
+ u.Visibility = setting.Service.DefaultUserVisibilityMode
u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation
u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification
u.MaxRepoCreation = -1
u.Theme = setting.UI.DefaultTheme
+ // overwrite defaults if set
+ if len(overwriteDefault) != 0 && overwriteDefault[0] != nil {
+ u.Visibility = overwriteDefault[0].Visibility
+ }
if _, err = sess.Insert(u); err != nil {
return err
@@ -1527,10 +1594,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
cond = cond.And(keywordCond)
}
+ // If visibility filtered
if len(opts.Visible) > 0 {
cond = cond.And(builder.In("visibility", opts.Visible))
- } else {
- cond = cond.And(builder.In("visibility", structs.VisibleTypePublic))
}
if opts.Actor != nil {
@@ -1543,16 +1609,27 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
exprCond = builder.Expr("org_user.org_id = \"user\".id")
}
- var accessCond builder.Cond
- if !opts.Actor.IsRestricted {
- accessCond = builder.Or(
- builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID}, builder.Eq{"visibility": structs.VisibleTypePrivate}))),
- builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
- } else {
- // restricted users only see orgs they are a member of
- accessCond = builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID})))
+ // If Admin - they see all users!
+ if !opts.Actor.IsAdmin {
+ // Force visiblity for privacy
+ var accessCond builder.Cond
+ if !opts.Actor.IsRestricted {
+ accessCond = builder.Or(
+ builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID}, builder.Eq{"visibility": structs.VisibleTypePrivate}))),
+ builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
+ } else {
+ // restricted users only see orgs they are a member of
+ accessCond = builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID})))
+ }
+ // Don't forget about self
+ accessCond = accessCond.Or(builder.Eq{"id": opts.Actor.ID})
+ cond = cond.And(accessCond)
}
- cond = cond.And(accessCond)
+
+ } else {
+ // Force visiblity for privacy
+ // Not logged in - only public users
+ cond = cond.And(builder.In("visibility", structs.VisibleTypePublic))
}
if opts.UID > 0 {