@@ -432,6 +432,62 @@ func (u *User) IsPasswordSet() bool {
432432 return len (u .Passwd ) != 0
433433}
434434
435+ // IsVisibleToUser check if viewer is able to see user profile
436+ func (u * User ) IsVisibleToUser (viewer * User ) bool {
437+ return u .isVisibleToUser (x , viewer )
438+ }
439+
440+ func (u * User ) isVisibleToUser (e Engine , viewer * User ) bool {
441+ if viewer != nil && viewer .IsAdmin {
442+ return true
443+ }
444+
445+ switch u .Visibility {
446+ case structs .VisibleTypePublic :
447+ return true
448+ case structs .VisibleTypeLimited :
449+ if viewer == nil || viewer .IsRestricted {
450+ return false
451+ }
452+ return true
453+ case structs .VisibleTypePrivate :
454+ if viewer == nil || viewer .IsRestricted {
455+ return false
456+ }
457+
458+ // If they follow - they see each over
459+ follower := IsFollowing (u .ID , viewer .ID )
460+ if follower {
461+ return true
462+ }
463+
464+ // Now we need to check if they in some organization together
465+ count , err := x .Table ("team_user" ).
466+ Where (
467+ builder .And (
468+ builder.Eq {"uid" : viewer .ID },
469+ builder .Or (
470+ builder.Eq {"org_id" : u .ID },
471+ builder .In ("org_id" ,
472+ builder .Select ("org_id" ).
473+ From ("team_user" , "t2" ).
474+ Where (builder.Eq {"uid" : u .ID }))))).
475+ Count (new (TeamUser ))
476+ if err != nil {
477+ return false
478+ }
479+
480+ if count < 0 {
481+ // No common organization
482+ return false
483+ }
484+
485+ // they are in an organization together
486+ return true
487+ }
488+ return false
489+ }
490+
435491// IsOrganization returns true if user is actually a organization.
436492func (u * User ) IsOrganization () bool {
437493 return u .Type == UserTypeOrganization
@@ -796,8 +852,13 @@ func IsUsableUsername(name string) error {
796852 return isUsableName (reservedUsernames , reservedUserPatterns , name )
797853}
798854
855+ // CreateUserOverwriteOptions are an optional options who overwrite system defaults on user creation
856+ type CreateUserOverwriteOptions struct {
857+ Visibility structs.VisibleType
858+ }
859+
799860// CreateUser creates record of a new user.
800- func CreateUser (u * User ) (err error ) {
861+ func CreateUser (u * User , overwriteDefault ... * CreateUserOverwriteOptions ) (err error ) {
801862 if err = IsUsableUsername (u .Name ); err != nil {
802863 return err
803864 }
@@ -831,8 +892,6 @@ func CreateUser(u *User) (err error) {
831892 return ErrEmailAlreadyUsed {u .Email }
832893 }
833894
834- u .KeepEmailPrivate = setting .Service .DefaultKeepEmailPrivate
835-
836895 u .LowerName = strings .ToLower (u .Name )
837896 u .AvatarEmail = u .Email
838897 if u .Rands , err = GetUserSalt (); err != nil {
@@ -841,10 +900,18 @@ func CreateUser(u *User) (err error) {
841900 if err = u .SetPassword (u .Passwd ); err != nil {
842901 return err
843902 }
903+
904+ // set system defaults
905+ u .KeepEmailPrivate = setting .Service .DefaultKeepEmailPrivate
906+ u .Visibility = setting .Service .DefaultUserVisibilityMode
844907 u .AllowCreateOrganization = setting .Service .DefaultAllowCreateOrganization && ! setting .Admin .DisableRegularOrgCreation
845908 u .EmailNotificationsPreference = setting .Admin .DefaultEmailNotification
846909 u .MaxRepoCreation = - 1
847910 u .Theme = setting .UI .DefaultTheme
911+ // overwrite defaults if set
912+ if len (overwriteDefault ) != 0 && overwriteDefault [0 ] != nil {
913+ u .Visibility = overwriteDefault [0 ].Visibility
914+ }
848915
849916 if _ , err = sess .Insert (u ); err != nil {
850917 return err
@@ -1527,10 +1594,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
15271594 cond = cond .And (keywordCond )
15281595 }
15291596
1597+ // If visibility filtered
15301598 if len (opts .Visible ) > 0 {
15311599 cond = cond .And (builder .In ("visibility" , opts .Visible ))
1532- } else {
1533- cond = cond .And (builder .In ("visibility" , structs .VisibleTypePublic ))
15341600 }
15351601
15361602 if opts .Actor != nil {
@@ -1543,16 +1609,27 @@ func (opts *SearchUserOptions) toConds() builder.Cond {
15431609 exprCond = builder .Expr ("org_user.org_id = \" user\" .id" )
15441610 }
15451611
1546- var accessCond builder.Cond
1547- if ! opts .Actor .IsRestricted {
1548- accessCond = builder .Or (
1549- 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 }))),
1550- builder .In ("visibility" , structs .VisibleTypePublic , structs .VisibleTypeLimited ))
1551- } else {
1552- // restricted users only see orgs they are a member of
1553- accessCond = builder .In ("id" , builder .Select ("org_id" ).From ("org_user" ).LeftJoin ("`user`" , exprCond ).Where (builder .And (builder.Eq {"uid" : opts .Actor .ID })))
1612+ // If Admin - they see all users!
1613+ if ! opts .Actor .IsAdmin {
1614+ // Force visiblity for privacy
1615+ var accessCond builder.Cond
1616+ if ! opts .Actor .IsRestricted {
1617+ accessCond = builder .Or (
1618+ 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 }))),
1619+ builder .In ("visibility" , structs .VisibleTypePublic , structs .VisibleTypeLimited ))
1620+ } else {
1621+ // restricted users only see orgs they are a member of
1622+ accessCond = builder .In ("id" , builder .Select ("org_id" ).From ("org_user" ).LeftJoin ("`user`" , exprCond ).Where (builder .And (builder.Eq {"uid" : opts .Actor .ID })))
1623+ }
1624+ // Don't forget about self
1625+ accessCond = accessCond .Or (builder.Eq {"id" : opts .Actor .ID })
1626+ cond = cond .And (accessCond )
15541627 }
1555- cond = cond .And (accessCond )
1628+
1629+ } else {
1630+ // Force visiblity for privacy
1631+ // Not logged in - only public users
1632+ cond = cond .And (builder .In ("visibility" , structs .VisibleTypePublic ))
15561633 }
15571634
15581635 if opts .UID > 0 {
0 commit comments