@@ -1462,46 +1462,18 @@ func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
1462
1462
return users , e .In ("id" , userIDs ).Find (& users )
1463
1463
}
1464
1464
1465
- // UpdateIssueMentions extracts mentioned people from content and
1466
- // updates issue-user relations for them.
1467
- func UpdateIssueMentions (e Engine , issueID int64 , mentions []string ) error {
1465
+ // UpdateIssueMentions updates issue-user relations for mentioned users.
1466
+ func UpdateIssueMentions (e Engine , issueID int64 , mentions []* User ) error {
1468
1467
if len (mentions ) == 0 {
1469
1468
return nil
1470
1469
}
1471
-
1472
- for i := range mentions {
1473
- mentions [i ] = strings .ToLower (mentions [i ])
1474
- }
1475
- users := make ([]* User , 0 , len (mentions ))
1476
-
1477
- if err := e .In ("lower_name" , mentions ).Asc ("lower_name" ).Find (& users ); err != nil {
1478
- return fmt .Errorf ("find mentioned users: %v" , err )
1470
+ ids := make ([]int64 , len (mentions ))
1471
+ for i , u := range mentions {
1472
+ ids [i ] = u .ID
1479
1473
}
1480
-
1481
- ids := make ([]int64 , 0 , len (mentions ))
1482
- for _ , user := range users {
1483
- ids = append (ids , user .ID )
1484
- if ! user .IsOrganization () || user .NumMembers == 0 {
1485
- continue
1486
- }
1487
-
1488
- memberIDs := make ([]int64 , 0 , user .NumMembers )
1489
- orgUsers , err := getOrgUsersByOrgID (e , user .ID )
1490
- if err != nil {
1491
- return fmt .Errorf ("GetOrgUsersByOrgID [%d]: %v" , user .ID , err )
1492
- }
1493
-
1494
- for _ , orgUser := range orgUsers {
1495
- memberIDs = append (memberIDs , orgUser .ID )
1496
- }
1497
-
1498
- ids = append (ids , memberIDs ... )
1499
- }
1500
-
1501
1474
if err := UpdateIssueUsersByMentions (e , issueID , ids ); err != nil {
1502
1475
return fmt .Errorf ("UpdateIssueUsersByMentions: %v" , err )
1503
1476
}
1504
-
1505
1477
return nil
1506
1478
}
1507
1479
@@ -1854,3 +1826,120 @@ func (issue *Issue) updateClosedNum(e Engine) (err error) {
1854
1826
}
1855
1827
return
1856
1828
}
1829
+
1830
+ // ResolveMentionsByVisibility returns the users mentioned in an issue, removing those that
1831
+ // don't have access to reading it. Teams are expanded into their users, but organizations are ignored.
1832
+ func (issue * Issue ) ResolveMentionsByVisibility (e Engine , doer * User , mentions []string ) (users []* User , err error ) {
1833
+ if len (mentions ) == 0 {
1834
+ return
1835
+ }
1836
+ if err = issue .loadRepo (e ); err != nil {
1837
+ return
1838
+ }
1839
+ resolved := make (map [string ]bool , 20 )
1840
+ names := make ([]string , 0 , 20 )
1841
+ resolved [doer .LowerName ] = true
1842
+ for _ , name := range mentions {
1843
+ name := strings .ToLower (name )
1844
+ if _ , ok := resolved [name ]; ok {
1845
+ continue
1846
+ }
1847
+ resolved [name ] = false
1848
+ names = append (names , name )
1849
+ }
1850
+
1851
+ if err := issue .Repo .getOwner (e ); err != nil {
1852
+ return nil , err
1853
+ }
1854
+
1855
+ if issue .Repo .Owner .IsOrganization () {
1856
+ // Since there can be users with names that match the name of a team,
1857
+ // if the team exists and can read the issue, the team takes precedence.
1858
+ teams := make ([]* Team , 0 , len (names ))
1859
+ if err := e .
1860
+ Join ("INNER" , "team_repo" , "team_repo.team_id = team.id" ).
1861
+ Where ("team_repo.repo_id=?" , issue .Repo .ID ).
1862
+ In ("team.lower_name" , names ).
1863
+ Find (& teams ); err != nil {
1864
+ return nil , fmt .Errorf ("find mentioned teams: %v" , err )
1865
+ }
1866
+ if len (teams ) != 0 {
1867
+ checked := make ([]int64 , 0 , len (teams ))
1868
+ unittype := UnitTypeIssues
1869
+ if issue .IsPull {
1870
+ unittype = UnitTypePullRequests
1871
+ }
1872
+ for _ , team := range teams {
1873
+ if team .Authorize >= AccessModeOwner {
1874
+ checked = append (checked , team .ID )
1875
+ resolved [team .LowerName ] = true
1876
+ continue
1877
+ }
1878
+ has , err := e .Get (& TeamUnit {OrgID : issue .Repo .Owner .ID , TeamID : team .ID , Type : unittype })
1879
+ if err != nil {
1880
+ return nil , fmt .Errorf ("get team units (%d): %v" , team .ID , err )
1881
+ }
1882
+ if has {
1883
+ checked = append (checked , team .ID )
1884
+ resolved [team .LowerName ] = true
1885
+ }
1886
+ }
1887
+ if len (checked ) != 0 {
1888
+ teamusers := make ([]* User , 0 , 20 )
1889
+ if err := e .
1890
+ Join ("INNER" , "team_user" , "team_user.uid = `user`.id" ).
1891
+ In ("`team_user`.team_id" , checked ).
1892
+ And ("`user`.is_active = ?" , true ).
1893
+ And ("`user`.prohibit_login = ?" , false ).
1894
+ Find (& teamusers ); err != nil {
1895
+ return nil , fmt .Errorf ("get teams users: %v" , err )
1896
+ }
1897
+ if len (teamusers ) > 0 {
1898
+ users = make ([]* User , 0 , len (teamusers ))
1899
+ for _ , user := range teamusers {
1900
+ if already , ok := resolved [user .LowerName ]; ! ok || ! already {
1901
+ users = append (users , user )
1902
+ resolved [user .LowerName ] = true
1903
+ }
1904
+ }
1905
+ }
1906
+ }
1907
+ }
1908
+
1909
+ // Remove names already in the list to avoid querying the database if pending names remain
1910
+ names = make ([]string , 0 , len (resolved ))
1911
+ for name , already := range resolved {
1912
+ if ! already {
1913
+ names = append (names , name )
1914
+ }
1915
+ }
1916
+ if len (names ) == 0 {
1917
+ return
1918
+ }
1919
+ }
1920
+
1921
+ unchecked := make ([]* User , 0 , len (names ))
1922
+ if err := e .
1923
+ Where ("`user`.is_active = ?" , true ).
1924
+ And ("`user`.prohibit_login = ?" , false ).
1925
+ In ("`user`.lower_name" , names ).
1926
+ Find (& unchecked ); err != nil {
1927
+ return nil , fmt .Errorf ("find mentioned users: %v" , err )
1928
+ }
1929
+ for _ , user := range unchecked {
1930
+ if already := resolved [user .LowerName ]; already || user .IsOrganization () {
1931
+ continue
1932
+ }
1933
+ // Normal users must have read access to the referencing issue
1934
+ perm , err := getUserRepoPermission (e , issue .Repo , user )
1935
+ if err != nil {
1936
+ return nil , fmt .Errorf ("getUserRepoPermission [%d]: %v" , user .ID , err )
1937
+ }
1938
+ if ! perm .CanReadIssuesOrPulls (issue .IsPull ) {
1939
+ continue
1940
+ }
1941
+ users = append (users , user )
1942
+ }
1943
+
1944
+ return
1945
+ }
0 commit comments