You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 9 години
преди 7 години
преди 9 години
преди 9 години
преди 7 години
преди 10 години
преди 9 години
преди 7 години
преди 7 години
преди 7 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 7 години
преди 7 години
преди 7 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 7 години
преди 7 години
преди 7 години
преди 10 години
преди 10 години
преди 5 години
преди 7 години
преди 7 години
преди 10 години
преди 7 години
преди 9 години
преди 7 години
преди 9 години
преди 10 години
преди 10 години
преди 6 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 10 години
преди 7 години
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
преди 5 години
преди 10 години
преди 10 години
преди 10 години
преди 7 години
преди 7 години
преди 10 години
преди 9 години
преди 7 години
преди 7 години
преди 7 години
преди 8 години
преди 5 години
преди 7 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 7 години
преди 7 години
преди 7 години
преди 5 години
преди 5 години
преди 7 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 5 години
преди 9 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 7 години
преди 5 години
преди 5 години
преди 8 години
преди 5 години
преди 5 години
преди 8 години
преди 5 години
преди 5 години
преди 7 години
преди 7 години
преди 7 години
преди 5 години
преди 7 години
преди 5 години
преди 7 години
преди 5 години
преди 7 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "errors"
  8. "fmt"
  9. "os"
  10. "strings"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/structs"
  13. "github.com/Unknwon/com"
  14. "github.com/go-xorm/builder"
  15. "github.com/go-xorm/xorm"
  16. )
  17. var (
  18. // ErrTeamNotExist team does not exist
  19. ErrTeamNotExist = errors.New("Team does not exist")
  20. )
  21. // IsOwnedBy returns true if given user is in the owner team.
  22. func (org *User) IsOwnedBy(uid int64) (bool, error) {
  23. return IsOrganizationOwner(org.ID, uid)
  24. }
  25. // IsOrgMember returns true if given user is member of organization.
  26. func (org *User) IsOrgMember(uid int64) (bool, error) {
  27. return IsOrganizationMember(org.ID, uid)
  28. }
  29. func (org *User) getTeam(e Engine, name string) (*Team, error) {
  30. return getTeam(e, org.ID, name)
  31. }
  32. // GetTeam returns named team of organization.
  33. func (org *User) GetTeam(name string) (*Team, error) {
  34. return org.getTeam(x, name)
  35. }
  36. func (org *User) getOwnerTeam(e Engine) (*Team, error) {
  37. return org.getTeam(e, ownerTeamName)
  38. }
  39. // GetOwnerTeam returns owner team of organization.
  40. func (org *User) GetOwnerTeam() (*Team, error) {
  41. return org.getOwnerTeam(x)
  42. }
  43. func (org *User) getTeams(e Engine) error {
  44. return e.
  45. Where("org_id=?", org.ID).
  46. OrderBy("CASE WHEN name LIKE '" + ownerTeamName + "' THEN '' ELSE name END").
  47. Find(&org.Teams)
  48. }
  49. // GetTeams returns all teams that belong to organization.
  50. func (org *User) GetTeams() error {
  51. return org.getTeams(x)
  52. }
  53. // GetMembers returns all members of organization.
  54. func (org *User) GetMembers() error {
  55. ous, err := GetOrgUsersByOrgID(org.ID)
  56. if err != nil {
  57. return err
  58. }
  59. var ids = make([]int64, len(ous))
  60. for i, ou := range ous {
  61. ids[i] = ou.UID
  62. }
  63. org.Members, err = GetUsersByIDs(ids)
  64. return err
  65. }
  66. // AddMember adds new member to organization.
  67. func (org *User) AddMember(uid int64) error {
  68. return AddOrgUser(org.ID, uid)
  69. }
  70. // RemoveMember removes member from organization.
  71. func (org *User) RemoveMember(uid int64) error {
  72. return RemoveOrgUser(org.ID, uid)
  73. }
  74. func (org *User) removeOrgRepo(e Engine, repoID int64) error {
  75. return removeOrgRepo(e, org.ID, repoID)
  76. }
  77. // RemoveOrgRepo removes all team-repository relations of organization.
  78. func (org *User) RemoveOrgRepo(repoID int64) error {
  79. return org.removeOrgRepo(x, repoID)
  80. }
  81. // CreateOrganization creates record of a new organization.
  82. func CreateOrganization(org, owner *User) (err error) {
  83. if !owner.CanCreateOrganization() {
  84. return ErrUserNotAllowedCreateOrg{}
  85. }
  86. if err = IsUsableUsername(org.Name); err != nil {
  87. return err
  88. }
  89. isExist, err := IsUserExist(0, org.Name)
  90. if err != nil {
  91. return err
  92. } else if isExist {
  93. return ErrUserAlreadyExist{org.Name}
  94. }
  95. org.LowerName = strings.ToLower(org.Name)
  96. if org.Rands, err = GetUserSalt(); err != nil {
  97. return err
  98. }
  99. if org.Salt, err = GetUserSalt(); err != nil {
  100. return err
  101. }
  102. org.UseCustomAvatar = true
  103. org.MaxRepoCreation = -1
  104. org.NumTeams = 1
  105. org.NumMembers = 1
  106. org.Type = UserTypeOrganization
  107. sess := x.NewSession()
  108. defer sess.Close()
  109. if err = sess.Begin(); err != nil {
  110. return err
  111. }
  112. if _, err = sess.Insert(org); err != nil {
  113. return fmt.Errorf("insert organization: %v", err)
  114. }
  115. if err = org.generateRandomAvatar(sess); err != nil {
  116. return fmt.Errorf("generate random avatar: %v", err)
  117. }
  118. // Add initial creator to organization and owner team.
  119. if _, err = sess.Insert(&OrgUser{
  120. UID: owner.ID,
  121. OrgID: org.ID,
  122. }); err != nil {
  123. return fmt.Errorf("insert org-user relation: %v", err)
  124. }
  125. // Create default owner team.
  126. t := &Team{
  127. OrgID: org.ID,
  128. LowerName: strings.ToLower(ownerTeamName),
  129. Name: ownerTeamName,
  130. Authorize: AccessModeOwner,
  131. NumMembers: 1,
  132. }
  133. if _, err = sess.Insert(t); err != nil {
  134. return fmt.Errorf("insert owner team: %v", err)
  135. }
  136. // insert units for team
  137. var units = make([]TeamUnit, 0, len(AllRepoUnitTypes))
  138. for _, tp := range AllRepoUnitTypes {
  139. units = append(units, TeamUnit{
  140. OrgID: org.ID,
  141. TeamID: t.ID,
  142. Type: tp,
  143. })
  144. }
  145. if _, err = sess.Insert(&units); err != nil {
  146. if err := sess.Rollback(); err != nil {
  147. log.Error("CreateOrganization: sess.Rollback: %v", err)
  148. }
  149. return err
  150. }
  151. if _, err = sess.Insert(&TeamUser{
  152. UID: owner.ID,
  153. OrgID: org.ID,
  154. TeamID: t.ID,
  155. }); err != nil {
  156. return fmt.Errorf("insert team-user relation: %v", err)
  157. }
  158. return sess.Commit()
  159. }
  160. // GetOrgByName returns organization by given name.
  161. func GetOrgByName(name string) (*User, error) {
  162. if len(name) == 0 {
  163. return nil, ErrOrgNotExist{0, name}
  164. }
  165. u := &User{
  166. LowerName: strings.ToLower(name),
  167. Type: UserTypeOrganization,
  168. }
  169. has, err := x.Get(u)
  170. if err != nil {
  171. return nil, err
  172. } else if !has {
  173. return nil, ErrOrgNotExist{0, name}
  174. }
  175. return u, nil
  176. }
  177. // CountOrganizations returns number of organizations.
  178. func CountOrganizations() int64 {
  179. count, _ := x.
  180. Where("type=1").
  181. Count(new(User))
  182. return count
  183. }
  184. // DeleteOrganization completely and permanently deletes everything of organization.
  185. func DeleteOrganization(org *User) (err error) {
  186. sess := x.NewSession()
  187. defer sess.Close()
  188. if err = sess.Begin(); err != nil {
  189. return err
  190. }
  191. if err = deleteOrg(sess, org); err != nil {
  192. if IsErrUserOwnRepos(err) {
  193. return err
  194. } else if err != nil {
  195. return fmt.Errorf("deleteOrg: %v", err)
  196. }
  197. }
  198. return sess.Commit()
  199. }
  200. func deleteOrg(e *xorm.Session, u *User) error {
  201. if !u.IsOrganization() {
  202. return fmt.Errorf("You can't delete none organization user: %s", u.Name)
  203. }
  204. // Check ownership of repository.
  205. count, err := getRepositoryCount(e, u)
  206. if err != nil {
  207. return fmt.Errorf("GetRepositoryCount: %v", err)
  208. } else if count > 0 {
  209. return ErrUserOwnRepos{UID: u.ID}
  210. }
  211. if err := deleteBeans(e,
  212. &Team{OrgID: u.ID},
  213. &OrgUser{OrgID: u.ID},
  214. &TeamUser{OrgID: u.ID},
  215. &TeamUnit{OrgID: u.ID},
  216. ); err != nil {
  217. return fmt.Errorf("deleteBeans: %v", err)
  218. }
  219. if _, err = e.ID(u.ID).Delete(new(User)); err != nil {
  220. return fmt.Errorf("Delete: %v", err)
  221. }
  222. // FIXME: system notice
  223. // Note: There are something just cannot be roll back,
  224. // so just keep error logs of those operations.
  225. path := UserPath(u.Name)
  226. if err := os.RemoveAll(path); err != nil {
  227. return fmt.Errorf("Failed to RemoveAll %s: %v", path, err)
  228. }
  229. if len(u.Avatar) > 0 {
  230. avatarPath := u.CustomAvatarPath()
  231. if com.IsExist(avatarPath) {
  232. if err := os.Remove(avatarPath); err != nil {
  233. return fmt.Errorf("Failed to remove %s: %v", avatarPath, err)
  234. }
  235. }
  236. }
  237. return nil
  238. }
  239. // ________ ____ ___
  240. // \_____ \_______ ____ | | \______ ___________
  241. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  242. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  243. // \_______ /__| \___ /|______//____ >\___ >__|
  244. // \/ /_____/ \/ \/
  245. // OrgUser represents an organization-user relation.
  246. type OrgUser struct {
  247. ID int64 `xorm:"pk autoincr"`
  248. UID int64 `xorm:"INDEX UNIQUE(s)"`
  249. OrgID int64 `xorm:"INDEX UNIQUE(s)"`
  250. IsPublic bool `xorm:"INDEX"`
  251. }
  252. func isOrganizationOwner(e Engine, orgID, uid int64) (bool, error) {
  253. ownerTeam := &Team{
  254. OrgID: orgID,
  255. Name: ownerTeamName,
  256. }
  257. if has, err := e.Get(ownerTeam); err != nil {
  258. return false, err
  259. } else if !has {
  260. log.Error("Organization does not have owner team: %d", orgID)
  261. return false, nil
  262. }
  263. return isTeamMember(e, orgID, ownerTeam.ID, uid)
  264. }
  265. // IsOrganizationOwner returns true if given user is in the owner team.
  266. func IsOrganizationOwner(orgID, uid int64) (bool, error) {
  267. return isOrganizationOwner(x, orgID, uid)
  268. }
  269. // IsOrganizationMember returns true if given user is member of organization.
  270. func IsOrganizationMember(orgID, uid int64) (bool, error) {
  271. return isOrganizationMember(x, orgID, uid)
  272. }
  273. func isOrganizationMember(e Engine, orgID, uid int64) (bool, error) {
  274. return e.
  275. Where("uid=?", uid).
  276. And("org_id=?", orgID).
  277. Table("org_user").
  278. Exist()
  279. }
  280. // IsPublicMembership returns true if given user public his/her membership.
  281. func IsPublicMembership(orgID, uid int64) (bool, error) {
  282. return x.
  283. Where("uid=?", uid).
  284. And("org_id=?", orgID).
  285. And("is_public=?", true).
  286. Table("org_user").
  287. Exist()
  288. }
  289. func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
  290. orgs := make([]*User, 0, 10)
  291. if !showAll {
  292. sess.And("`org_user`.is_public=?", true)
  293. }
  294. return orgs, sess.
  295. And("`org_user`.uid=?", userID).
  296. Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").
  297. Asc("`user`.name").
  298. Find(&orgs)
  299. }
  300. // GetOrgsByUserID returns a list of organizations that the given user ID
  301. // has joined.
  302. func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
  303. sess := x.NewSession()
  304. defer sess.Close()
  305. return getOrgsByUserID(sess, userID, showAll)
  306. }
  307. func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
  308. orgs := make([]*User, 0, 10)
  309. return orgs, sess.
  310. Join("INNER", "`team_user`", "`team_user`.org_id=`user`.id").
  311. Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
  312. Where("`team_user`.uid=?", userID).
  313. And("`team`.authorize=?", AccessModeOwner).
  314. Asc("`user`.name").
  315. Find(&orgs)
  316. }
  317. // HasOrgVisible tells if the given user can see the given org
  318. func HasOrgVisible(org *User, user *User) bool {
  319. return hasOrgVisible(x, org, user)
  320. }
  321. func hasOrgVisible(e Engine, org *User, user *User) bool {
  322. // Not SignedUser
  323. if user == nil {
  324. return org.Visibility == structs.VisibleTypePublic
  325. }
  326. if user.IsAdmin {
  327. return true
  328. }
  329. if org.Visibility == structs.VisibleTypePrivate && !org.isUserPartOfOrg(e, user.ID) {
  330. return false
  331. }
  332. return true
  333. }
  334. // HasOrgsVisible tells if the given user can see at least one of the orgs provided
  335. func HasOrgsVisible(orgs []*User, user *User) bool {
  336. if len(orgs) == 0 {
  337. return false
  338. }
  339. for _, org := range orgs {
  340. if HasOrgVisible(org, user) {
  341. return true
  342. }
  343. }
  344. return false
  345. }
  346. // GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
  347. func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
  348. sess := x.NewSession()
  349. defer sess.Close()
  350. return getOwnedOrgsByUserID(sess, userID)
  351. }
  352. // GetOwnedOrgsByUserIDDesc returns a list of organizations are owned by
  353. // given user ID, ordered descending by the given condition.
  354. func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
  355. return getOwnedOrgsByUserID(x.Desc(desc), userID)
  356. }
  357. // GetOrgUsersByUserID returns all organization-user relations by user ID.
  358. func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
  359. ous := make([]*OrgUser, 0, 10)
  360. sess := x.
  361. Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
  362. Where("`org_user`.uid=?", uid)
  363. if !all {
  364. // Only show public organizations
  365. sess.And("is_public=?", true)
  366. }
  367. err := sess.
  368. Asc("`user`.name").
  369. Find(&ous)
  370. return ous, err
  371. }
  372. // GetOrgUsersByOrgID returns all organization-user relations by organization ID.
  373. func GetOrgUsersByOrgID(orgID int64) ([]*OrgUser, error) {
  374. return getOrgUsersByOrgID(x, orgID)
  375. }
  376. func getOrgUsersByOrgID(e Engine, orgID int64) ([]*OrgUser, error) {
  377. ous := make([]*OrgUser, 0, 10)
  378. err := e.
  379. Where("org_id=?", orgID).
  380. Find(&ous)
  381. return ous, err
  382. }
  383. // ChangeOrgUserStatus changes public or private membership status.
  384. func ChangeOrgUserStatus(orgID, uid int64, public bool) error {
  385. ou := new(OrgUser)
  386. has, err := x.
  387. Where("uid=?", uid).
  388. And("org_id=?", orgID).
  389. Get(ou)
  390. if err != nil {
  391. return err
  392. } else if !has {
  393. return nil
  394. }
  395. ou.IsPublic = public
  396. _, err = x.ID(ou.ID).Cols("is_public").Update(ou)
  397. return err
  398. }
  399. // AddOrgUser adds new user to given organization.
  400. func AddOrgUser(orgID, uid int64) error {
  401. isAlreadyMember, err := IsOrganizationMember(orgID, uid)
  402. if err != nil || isAlreadyMember {
  403. return err
  404. }
  405. sess := x.NewSession()
  406. defer sess.Close()
  407. if err := sess.Begin(); err != nil {
  408. return err
  409. }
  410. ou := &OrgUser{
  411. UID: uid,
  412. OrgID: orgID,
  413. }
  414. if _, err := sess.Insert(ou); err != nil {
  415. if err := sess.Rollback(); err != nil {
  416. log.Error("AddOrgUser: sess.Rollback: %v", err)
  417. }
  418. return err
  419. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil {
  420. if err := sess.Rollback(); err != nil {
  421. log.Error("AddOrgUser: sess.Rollback: %v", err)
  422. }
  423. return err
  424. }
  425. return sess.Commit()
  426. }
  427. func removeOrgUser(sess *xorm.Session, orgID, userID int64) error {
  428. ou := new(OrgUser)
  429. has, err := sess.
  430. Where("uid=?", userID).
  431. And("org_id=?", orgID).
  432. Get(ou)
  433. if err != nil {
  434. return fmt.Errorf("get org-user: %v", err)
  435. } else if !has {
  436. return nil
  437. }
  438. org, err := getUserByID(sess, orgID)
  439. if err != nil {
  440. return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
  441. }
  442. // Check if the user to delete is the last member in owner team.
  443. if isOwner, err := isOrganizationOwner(sess, orgID, userID); err != nil {
  444. return err
  445. } else if isOwner {
  446. t, err := org.getOwnerTeam(sess)
  447. if err != nil {
  448. return err
  449. }
  450. if t.NumMembers == 1 {
  451. if err := t.getMembers(sess); err != nil {
  452. return err
  453. }
  454. if t.Members[0].ID == userID {
  455. return ErrLastOrgOwner{UID: userID}
  456. }
  457. }
  458. }
  459. if _, err := sess.ID(ou.ID).Delete(ou); err != nil {
  460. return err
  461. } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgID); err != nil {
  462. return err
  463. }
  464. // Delete all repository accesses and unwatch them.
  465. env, err := org.accessibleReposEnv(sess, userID)
  466. if err != nil {
  467. return fmt.Errorf("AccessibleReposEnv: %v", err)
  468. }
  469. repoIDs, err := env.RepoIDs(1, org.NumRepos)
  470. if err != nil {
  471. return fmt.Errorf("GetUserRepositories [%d]: %v", userID, err)
  472. }
  473. for _, repoID := range repoIDs {
  474. if err = watchRepo(sess, userID, repoID, false); err != nil {
  475. return err
  476. }
  477. }
  478. if len(repoIDs) > 0 {
  479. if _, err = sess.
  480. Where("user_id = ?", userID).
  481. In("repo_id", repoIDs).
  482. Delete(new(Access)); err != nil {
  483. return err
  484. }
  485. }
  486. // Delete member in his/her teams.
  487. teams, err := getUserOrgTeams(sess, org.ID, userID)
  488. if err != nil {
  489. return err
  490. }
  491. for _, t := range teams {
  492. if err = removeTeamMember(sess, t, userID); err != nil {
  493. return err
  494. }
  495. }
  496. return nil
  497. }
  498. // RemoveOrgUser removes user from given organization.
  499. func RemoveOrgUser(orgID, userID int64) error {
  500. sess := x.NewSession()
  501. defer sess.Close()
  502. if err := sess.Begin(); err != nil {
  503. return err
  504. }
  505. if err := removeOrgUser(sess, orgID, userID); err != nil {
  506. return err
  507. }
  508. return sess.Commit()
  509. }
  510. func removeOrgRepo(e Engine, orgID, repoID int64) error {
  511. teamRepos := make([]*TeamRepo, 0, 10)
  512. if err := e.Find(&teamRepos, &TeamRepo{OrgID: orgID, RepoID: repoID}); err != nil {
  513. return err
  514. }
  515. if len(teamRepos) == 0 {
  516. return nil
  517. }
  518. if _, err := e.Delete(&TeamRepo{
  519. OrgID: orgID,
  520. RepoID: repoID,
  521. }); err != nil {
  522. return err
  523. }
  524. teamIDs := make([]int64, len(teamRepos))
  525. for i, teamRepo := range teamRepos {
  526. teamIDs[i] = teamRepo.TeamID
  527. }
  528. _, err := e.Decr("num_repos").In("id", teamIDs).Update(new(Team))
  529. return err
  530. }
  531. func (org *User) getUserTeams(e Engine, userID int64, cols ...string) ([]*Team, error) {
  532. teams := make([]*Team, 0, org.NumTeams)
  533. return teams, e.
  534. Where("`team_user`.org_id = ?", org.ID).
  535. Join("INNER", "team_user", "`team_user`.team_id = team.id").
  536. Join("INNER", "`user`", "`user`.id=team_user.uid").
  537. And("`team_user`.uid = ?", userID).
  538. Asc("`user`.name").
  539. Cols(cols...).
  540. Find(&teams)
  541. }
  542. func (org *User) getUserTeamIDs(e Engine, userID int64) ([]int64, error) {
  543. teamIDs := make([]int64, 0, org.NumTeams)
  544. return teamIDs, e.
  545. Table("team").
  546. Cols("team.id").
  547. Where("`team_user`.org_id = ?", org.ID).
  548. Join("INNER", "team_user", "`team_user`.team_id = team.id").
  549. And("`team_user`.uid = ?", userID).
  550. Find(&teamIDs)
  551. }
  552. // TeamsWithAccessToRepo returns all teamsthat have given access level to the repository.
  553. func (org *User) TeamsWithAccessToRepo(repoID int64, mode AccessMode) ([]*Team, error) {
  554. return GetTeamsWithAccessToRepo(org.ID, repoID, mode)
  555. }
  556. // GetUserTeamIDs returns of all team IDs of the organization that user is member of.
  557. func (org *User) GetUserTeamIDs(userID int64) ([]int64, error) {
  558. return org.getUserTeamIDs(x, userID)
  559. }
  560. // GetUserTeams returns all teams that belong to user,
  561. // and that the user has joined.
  562. func (org *User) GetUserTeams(userID int64) ([]*Team, error) {
  563. return org.getUserTeams(x, userID)
  564. }
  565. // AccessibleReposEnvironment operations involving the repositories that are
  566. // accessible to a particular user
  567. type AccessibleReposEnvironment interface {
  568. CountRepos() (int64, error)
  569. RepoIDs(page, pageSize int) ([]int64, error)
  570. Repos(page, pageSize int) ([]*Repository, error)
  571. MirrorRepos() ([]*Repository, error)
  572. AddKeyword(keyword string)
  573. SetSort(SearchOrderBy)
  574. }
  575. type accessibleReposEnv struct {
  576. org *User
  577. userID int64
  578. teamIDs []int64
  579. e Engine
  580. keyword string
  581. orderBy SearchOrderBy
  582. }
  583. // AccessibleReposEnv an AccessibleReposEnvironment for the repositories in `org`
  584. // that are accessible to the specified user.
  585. func (org *User) AccessibleReposEnv(userID int64) (AccessibleReposEnvironment, error) {
  586. return org.accessibleReposEnv(x, userID)
  587. }
  588. func (org *User) accessibleReposEnv(e Engine, userID int64) (AccessibleReposEnvironment, error) {
  589. teamIDs, err := org.getUserTeamIDs(e, userID)
  590. if err != nil {
  591. return nil, err
  592. }
  593. return &accessibleReposEnv{
  594. org: org,
  595. userID: userID,
  596. teamIDs: teamIDs,
  597. e: e,
  598. orderBy: SearchOrderByRecentUpdated,
  599. }, nil
  600. }
  601. func (env *accessibleReposEnv) cond() builder.Cond {
  602. var cond builder.Cond = builder.Eq{
  603. "`repository`.owner_id": env.org.ID,
  604. "`repository`.is_private": false,
  605. }
  606. if len(env.teamIDs) > 0 {
  607. cond = cond.Or(builder.In("team_repo.team_id", env.teamIDs))
  608. }
  609. if env.keyword != "" {
  610. cond = cond.And(builder.Like{"`repository`.lower_name", strings.ToLower(env.keyword)})
  611. }
  612. return cond
  613. }
  614. func (env *accessibleReposEnv) CountRepos() (int64, error) {
  615. repoCount, err := env.e.
  616. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
  617. Where(env.cond()).
  618. Distinct("`repository`.id").
  619. Count(&Repository{})
  620. if err != nil {
  621. return 0, fmt.Errorf("count user repositories in organization: %v", err)
  622. }
  623. return repoCount, nil
  624. }
  625. func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
  626. if page <= 0 {
  627. page = 1
  628. }
  629. repoIDs := make([]int64, 0, pageSize)
  630. return repoIDs, env.e.
  631. Table("repository").
  632. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
  633. Where(env.cond()).
  634. GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
  635. OrderBy(string(env.orderBy)).
  636. Limit(pageSize, (page-1)*pageSize).
  637. Cols("`repository`.id").
  638. Find(&repoIDs)
  639. }
  640. func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*Repository, error) {
  641. repoIDs, err := env.RepoIDs(page, pageSize)
  642. if err != nil {
  643. return nil, fmt.Errorf("GetUserRepositoryIDs: %v", err)
  644. }
  645. repos := make([]*Repository, 0, len(repoIDs))
  646. if len(repoIDs) == 0 {
  647. return repos, nil
  648. }
  649. return repos, env.e.
  650. In("`repository`.id", repoIDs).
  651. OrderBy(string(env.orderBy)).
  652. Find(&repos)
  653. }
  654. func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
  655. repoIDs := make([]int64, 0, 10)
  656. return repoIDs, env.e.
  657. Table("repository").
  658. Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
  659. Where(env.cond()).
  660. GroupBy("`repository`.id, `repository`.updated_unix").
  661. OrderBy(string(env.orderBy)).
  662. Cols("`repository`.id").
  663. Find(&repoIDs)
  664. }
  665. func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
  666. repoIDs, err := env.MirrorRepoIDs()
  667. if err != nil {
  668. return nil, fmt.Errorf("MirrorRepoIDs: %v", err)
  669. }
  670. repos := make([]*Repository, 0, len(repoIDs))
  671. if len(repoIDs) == 0 {
  672. return repos, nil
  673. }
  674. return repos, env.e.
  675. In("`repository`.id", repoIDs).
  676. Find(&repos)
  677. }
  678. func (env *accessibleReposEnv) AddKeyword(keyword string) {
  679. env.keyword = keyword
  680. }
  681. func (env *accessibleReposEnv) SetSort(orderBy SearchOrderBy) {
  682. env.orderBy = orderBy
  683. }