org.go 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "errors"
  7. "fmt"
  8. "os"
  9. "strings"
  10. "github.com/gogits/gogs/modules/base"
  11. )
  12. var (
  13. ErrOrgNotExist = errors.New("Organization does not exist")
  14. ErrTeamAlreadyExist = errors.New("Team already exist")
  15. ErrTeamNotExist = errors.New("Team does not exist")
  16. ErrTeamNameIllegal = errors.New("Team name contains illegal characters")
  17. ErrLastOrgOwner = errors.New("The user to remove is the last member in owner team")
  18. )
  19. // IsOwnedBy returns true if given user is in the owner team.
  20. func (org *User) IsOwnedBy(uid int64) bool {
  21. return IsOrganizationOwner(org.Id, uid)
  22. }
  23. // IsOrgMember returns true if given user is member of organization.
  24. func (org *User) IsOrgMember(uid int64) bool {
  25. return org.IsOrganization() && IsOrganizationMember(org.Id, uid)
  26. }
  27. func (org *User) getTeam(e Engine, name string) (*Team, error) {
  28. return getTeam(e, org.Id, name)
  29. }
  30. // GetTeam returns named team of organization.
  31. func (org *User) GetTeam(name string) (*Team, error) {
  32. return org.getTeam(x, name)
  33. }
  34. func (org *User) getOwnerTeam(e Engine) (*Team, error) {
  35. return org.getTeam(e, OWNER_TEAM)
  36. }
  37. // GetOwnerTeam returns owner team of organization.
  38. func (org *User) GetOwnerTeam() (*Team, error) {
  39. return org.getOwnerTeam(x)
  40. }
  41. func (org *User) getTeams(e Engine) error {
  42. return e.Where("org_id=?", org.Id).Find(&org.Teams)
  43. }
  44. // GetTeams returns all teams that belong to organization.
  45. func (org *User) GetTeams() error {
  46. return org.getTeams(x)
  47. }
  48. // GetMembers returns all members of organization.
  49. func (org *User) GetMembers() error {
  50. ous, err := GetOrgUsersByOrgId(org.Id)
  51. if err != nil {
  52. return err
  53. }
  54. org.Members = make([]*User, len(ous))
  55. for i, ou := range ous {
  56. org.Members[i], err = GetUserById(ou.Uid)
  57. if err != nil {
  58. return err
  59. }
  60. }
  61. return nil
  62. }
  63. // AddMember adds new member to organization.
  64. func (org *User) AddMember(uid int64) error {
  65. return AddOrgUser(org.Id, uid)
  66. }
  67. // RemoveMember removes member from organization.
  68. func (org *User) RemoveMember(uid int64) error {
  69. return RemoveOrgUser(org.Id, uid)
  70. }
  71. func (org *User) removeOrgRepo(e Engine, repoID int64) error {
  72. return removeOrgRepo(e, org.Id, repoID)
  73. }
  74. // RemoveOrgRepo removes all team-repository relations of organization.
  75. func (org *User) RemoveOrgRepo(repoID int64) error {
  76. return org.removeOrgRepo(x, repoID)
  77. }
  78. // IsOrgEmailUsed returns true if the e-mail has been used in organization account.
  79. func IsOrgEmailUsed(email string) (bool, error) {
  80. if len(email) == 0 {
  81. return false, nil
  82. }
  83. return x.Get(&User{
  84. Email: email,
  85. Type: ORGANIZATION,
  86. })
  87. }
  88. // CreateOrganization creates record of a new organization.
  89. func CreateOrganization(org, owner *User) (*User, error) {
  90. if !IsLegalName(org.Name) {
  91. return nil, ErrUserNameIllegal
  92. }
  93. isExist, err := IsUserExist(0, org.Name)
  94. if err != nil {
  95. return nil, err
  96. } else if isExist {
  97. return nil, ErrUserAlreadyExist
  98. }
  99. isExist, err = IsOrgEmailUsed(org.Email)
  100. if err != nil {
  101. return nil, err
  102. } else if isExist {
  103. return nil, ErrEmailAlreadyUsed
  104. }
  105. org.LowerName = strings.ToLower(org.Name)
  106. org.FullName = org.Name
  107. org.Avatar = base.EncodeMd5(org.Email)
  108. org.AvatarEmail = org.Email
  109. // No password for organization.
  110. org.NumTeams = 1
  111. org.NumMembers = 1
  112. sess := x.NewSession()
  113. defer sessionRelease(sess)
  114. if err = sess.Begin(); err != nil {
  115. return nil, err
  116. }
  117. if _, err = sess.Insert(org); err != nil {
  118. return nil, err
  119. }
  120. // Create default owner team.
  121. t := &Team{
  122. OrgID: org.Id,
  123. LowerName: strings.ToLower(OWNER_TEAM),
  124. Name: OWNER_TEAM,
  125. Authorize: ACCESS_MODE_OWNER,
  126. NumMembers: 1,
  127. }
  128. if _, err = sess.Insert(t); err != nil {
  129. return nil, err
  130. }
  131. // Add initial creator to organization and owner team.
  132. ou := &OrgUser{
  133. Uid: owner.Id,
  134. OrgID: org.Id,
  135. IsOwner: true,
  136. NumTeams: 1,
  137. }
  138. if _, err = sess.Insert(ou); err != nil {
  139. return nil, err
  140. }
  141. tu := &TeamUser{
  142. Uid: owner.Id,
  143. OrgID: org.Id,
  144. TeamID: t.ID,
  145. }
  146. if _, err = sess.Insert(tu); err != nil {
  147. return nil, err
  148. }
  149. if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
  150. return nil, err
  151. }
  152. return org, sess.Commit()
  153. }
  154. // GetOrgByName returns organization by given name.
  155. func GetOrgByName(name string) (*User, error) {
  156. if len(name) == 0 {
  157. return nil, ErrOrgNotExist
  158. }
  159. u := &User{
  160. LowerName: strings.ToLower(name),
  161. Type: ORGANIZATION,
  162. }
  163. has, err := x.Get(u)
  164. if err != nil {
  165. return nil, err
  166. } else if !has {
  167. return nil, ErrOrgNotExist
  168. }
  169. return u, nil
  170. }
  171. // CountOrganizations returns number of organizations.
  172. func CountOrganizations() int64 {
  173. count, _ := x.Where("type=1").Count(new(User))
  174. return count
  175. }
  176. // GetOrganizations returns given number of organizations with offset.
  177. func GetOrganizations(num, offset int) ([]*User, error) {
  178. orgs := make([]*User, 0, num)
  179. err := x.Limit(num, offset).Where("type=1").Asc("id").Find(&orgs)
  180. return orgs, err
  181. }
  182. // TODO: need some kind of mechanism to record failure.
  183. // DeleteOrganization completely and permanently deletes everything of organization.
  184. func DeleteOrganization(org *User) (err error) {
  185. if err := DeleteUser(org); err != nil {
  186. return err
  187. }
  188. sess := x.NewSession()
  189. defer sess.Close()
  190. if err = sess.Begin(); err != nil {
  191. return err
  192. }
  193. if _, err = sess.Delete(&Team{OrgID: org.Id}); err != nil {
  194. sess.Rollback()
  195. return err
  196. }
  197. if _, err = sess.Delete(&OrgUser{OrgID: org.Id}); err != nil {
  198. sess.Rollback()
  199. return err
  200. }
  201. if _, err = sess.Delete(&TeamUser{OrgID: org.Id}); err != nil {
  202. sess.Rollback()
  203. return err
  204. }
  205. return sess.Commit()
  206. }
  207. // ________ ____ ___
  208. // \_____ \_______ ____ | | \______ ___________
  209. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  210. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  211. // \_______ /__| \___ /|______//____ >\___ >__|
  212. // \/ /_____/ \/ \/
  213. // OrgUser represents an organization-user relation.
  214. type OrgUser struct {
  215. ID int64 `xorm:"pk autoincr"`
  216. Uid int64 `xorm:"INDEX UNIQUE(s)"`
  217. OrgID int64 `xorm:"INDEX UNIQUE(s)"`
  218. IsPublic bool
  219. IsOwner bool
  220. NumTeams int
  221. }
  222. // IsOrganizationOwner returns true if given user is in the owner team.
  223. func IsOrganizationOwner(orgId, uid int64) bool {
  224. has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  225. return has
  226. }
  227. // IsOrganizationMember returns true if given user is member of organization.
  228. func IsOrganizationMember(orgId, uid int64) bool {
  229. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  230. return has
  231. }
  232. // IsPublicMembership returns true if given user public his/her membership.
  233. func IsPublicMembership(orgId, uid int64) bool {
  234. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("is_public=?", true).Get(new(OrgUser))
  235. return has
  236. }
  237. // GetOrgUsersByUserId returns all organization-user relations by user ID.
  238. func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
  239. ous := make([]*OrgUser, 0, 10)
  240. err := x.Where("uid=?", uid).Find(&ous)
  241. return ous, err
  242. }
  243. // GetOrgUsersByOrgId returns all organization-user relations by organization ID.
  244. func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
  245. ous := make([]*OrgUser, 0, 10)
  246. err := x.Where("org_id=?", orgId).Find(&ous)
  247. return ous, err
  248. }
  249. // ChangeOrgUserStatus changes public or private membership status.
  250. func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
  251. ou := new(OrgUser)
  252. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  253. if err != nil {
  254. return err
  255. } else if !has {
  256. return nil
  257. }
  258. ou.IsPublic = public
  259. _, err = x.Id(ou.ID).AllCols().Update(ou)
  260. return err
  261. }
  262. // AddOrgUser adds new user to given organization.
  263. func AddOrgUser(orgId, uid int64) error {
  264. if IsOrganizationMember(orgId, uid) {
  265. return nil
  266. }
  267. sess := x.NewSession()
  268. defer sess.Close()
  269. if err := sess.Begin(); err != nil {
  270. return err
  271. }
  272. ou := &OrgUser{
  273. Uid: uid,
  274. OrgID: orgId,
  275. }
  276. if _, err := sess.Insert(ou); err != nil {
  277. sess.Rollback()
  278. return err
  279. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgId); err != nil {
  280. sess.Rollback()
  281. return err
  282. }
  283. return sess.Commit()
  284. }
  285. // RemoveOrgUser removes user from given organization.
  286. func RemoveOrgUser(orgId, uid int64) error {
  287. ou := new(OrgUser)
  288. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  289. if err != nil {
  290. return err
  291. } else if !has {
  292. return nil
  293. }
  294. u, err := GetUserById(uid)
  295. if err != nil {
  296. return err
  297. }
  298. org, err := GetUserById(orgId)
  299. if err != nil {
  300. return err
  301. }
  302. // Check if the user to delete is the last member in owner team.
  303. if IsOrganizationOwner(orgId, uid) {
  304. t, err := org.GetOwnerTeam()
  305. if err != nil {
  306. return err
  307. }
  308. if t.NumMembers == 1 {
  309. return ErrLastOrgOwner
  310. }
  311. }
  312. sess := x.NewSession()
  313. defer sess.Close()
  314. if err := sess.Begin(); err != nil {
  315. return err
  316. }
  317. if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
  318. sess.Rollback()
  319. return err
  320. } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id = ?", orgId); err != nil {
  321. sess.Rollback()
  322. return err
  323. }
  324. // Delete all repository accesses.
  325. if err = org.GetRepositories(); err != nil {
  326. sess.Rollback()
  327. return err
  328. }
  329. access := &Access{
  330. UserID: u.Id,
  331. }
  332. for _, repo := range org.Repos {
  333. access.RepoID = repo.Id
  334. if _, err = sess.Delete(access); err != nil {
  335. sess.Rollback()
  336. return err
  337. } else if err = WatchRepo(u.Id, repo.Id, false); err != nil {
  338. sess.Rollback()
  339. return err
  340. }
  341. }
  342. // Delete member in his/her teams.
  343. ts, err := GetUserTeams(org.Id, u.Id)
  344. if err != nil {
  345. return err
  346. }
  347. for _, t := range ts {
  348. if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
  349. return err
  350. }
  351. }
  352. return sess.Commit()
  353. }
  354. // ___________
  355. // \__ ___/___ _____ _____
  356. // | |_/ __ \\__ \ / \
  357. // | |\ ___/ / __ \| Y Y \
  358. // |____| \___ >____ /__|_| /
  359. // \/ \/ \/
  360. const OWNER_TEAM = "Owners"
  361. // Team represents a organization team.
  362. type Team struct {
  363. ID int64 `xorm:"pk autoincr"`
  364. OrgID int64 `xorm:"INDEX"`
  365. LowerName string
  366. Name string
  367. Description string
  368. Authorize AccessMode
  369. Repos []*Repository `xorm:"-"`
  370. Members []*User `xorm:"-"`
  371. NumRepos int
  372. NumMembers int
  373. }
  374. // IsOwnerTeam returns true if team is owner team.
  375. func (t *Team) IsOwnerTeam() bool {
  376. return t.Name == OWNER_TEAM
  377. }
  378. // IsTeamMember returns true if given user is a member of team.
  379. func (t *Team) IsMember(uid int64) bool {
  380. return IsTeamMember(t.OrgID, t.ID, uid)
  381. }
  382. func (t *Team) getRepositories(e Engine) (err error) {
  383. teamRepos := make([]*TeamRepo, 0, t.NumRepos)
  384. if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil {
  385. return fmt.Errorf("get team-repos: %v", err)
  386. }
  387. t.Repos = make([]*Repository, 0, len(teamRepos))
  388. for i := range teamRepos {
  389. repo, err := getRepositoryById(e, teamRepos[i].RepoID)
  390. if err != nil {
  391. return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err)
  392. }
  393. t.Repos = append(t.Repos, repo)
  394. }
  395. return nil
  396. }
  397. // GetRepositories returns all repositories in team of organization.
  398. func (t *Team) GetRepositories() error {
  399. return t.getRepositories(x)
  400. }
  401. func (t *Team) getMembers(e Engine) (err error) {
  402. t.Members, err = getTeamMembers(e, t.ID)
  403. return err
  404. }
  405. // GetMembers returns all members in team of organization.
  406. func (t *Team) GetMembers() (err error) {
  407. return t.getMembers(x)
  408. }
  409. // AddMember adds new member to team of organization.
  410. func (t *Team) AddMember(uid int64) error {
  411. return AddTeamMember(t.OrgID, t.ID, uid)
  412. }
  413. // RemoveMember removes member from team of organization.
  414. func (t *Team) RemoveMember(uid int64) error {
  415. return RemoveTeamMember(t.OrgID, t.ID, uid)
  416. }
  417. func (t *Team) hasRepository(e Engine, repoID int64) bool {
  418. return hasTeamRepo(e, t.OrgID, t.ID, repoID)
  419. }
  420. // HasRepository returns true if given repository belong to team.
  421. func (t *Team) HasRepository(repoID int64) bool {
  422. return HasTeamRepo(t.OrgID, t.ID, repoID)
  423. }
  424. func (t *Team) addRepository(e Engine, repo *Repository) (err error) {
  425. if err = addTeamRepo(e, t.OrgID, t.ID, repo.Id); err != nil {
  426. return err
  427. }
  428. t.NumRepos++
  429. if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
  430. return fmt.Errorf("update team: %v", err)
  431. }
  432. if err = repo.recalculateTeamAccesses(e, 0); err != nil {
  433. return fmt.Errorf("recalculateAccesses: %v", err)
  434. }
  435. if err = t.getMembers(e); err != nil {
  436. return fmt.Errorf("getMembers: %v", err)
  437. }
  438. for _, u := range t.Members {
  439. if err = watchRepo(e, u.Id, repo.Id, true); err != nil {
  440. return fmt.Errorf("watchRepo: %v", err)
  441. }
  442. }
  443. return nil
  444. }
  445. // AddRepository adds new repository to team of organization.
  446. func (t *Team) AddRepository(repo *Repository) (err error) {
  447. if repo.OwnerId != t.OrgID {
  448. return errors.New("Repository does not belong to organization")
  449. } else if t.HasRepository(repo.Id) {
  450. return nil
  451. }
  452. sess := x.NewSession()
  453. defer sessionRelease(sess)
  454. if err = sess.Begin(); err != nil {
  455. return err
  456. }
  457. if err = t.addRepository(sess, repo); err != nil {
  458. return err
  459. }
  460. return sess.Commit()
  461. }
  462. func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (err error) {
  463. if err = removeTeamRepo(e, t.ID, repo.Id); err != nil {
  464. return err
  465. }
  466. t.NumRepos--
  467. if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
  468. return err
  469. }
  470. // Don't need to recalculate when delete a repository from organization.
  471. if recalculate {
  472. if err = repo.recalculateTeamAccesses(e, t.ID); err != nil {
  473. return err
  474. }
  475. }
  476. if err = t.getMembers(e); err != nil {
  477. return fmt.Errorf("get team members: %v", err)
  478. }
  479. for _, u := range t.Members {
  480. has, err := hasAccess(e, u, repo, ACCESS_MODE_READ)
  481. if err != nil {
  482. return err
  483. } else if has {
  484. continue
  485. }
  486. if err = watchRepo(e, u.Id, repo.Id, false); err != nil {
  487. return err
  488. }
  489. }
  490. return nil
  491. }
  492. // RemoveRepository removes repository from team of organization.
  493. func (t *Team) RemoveRepository(repoID int64) error {
  494. if !t.HasRepository(repoID) {
  495. return nil
  496. }
  497. repo, err := GetRepositoryById(repoID)
  498. if err != nil {
  499. return err
  500. }
  501. sess := x.NewSession()
  502. defer sessionRelease(sess)
  503. if err = sess.Begin(); err != nil {
  504. return err
  505. }
  506. if err = t.removeRepository(sess, repo, true); err != nil {
  507. return err
  508. }
  509. return sess.Commit()
  510. }
  511. // NewTeam creates a record of new team.
  512. // It's caller's responsibility to assign organization ID.
  513. func NewTeam(t *Team) error {
  514. if !IsLegalName(t.Name) {
  515. return ErrTeamNameIllegal
  516. }
  517. has, err := x.Id(t.OrgID).Get(new(User))
  518. if err != nil {
  519. return err
  520. } else if !has {
  521. return ErrOrgNotExist
  522. }
  523. t.LowerName = strings.ToLower(t.Name)
  524. has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team))
  525. if err != nil {
  526. return err
  527. } else if has {
  528. return ErrTeamAlreadyExist
  529. }
  530. sess := x.NewSession()
  531. defer sess.Close()
  532. if err = sess.Begin(); err != nil {
  533. return err
  534. }
  535. if _, err = sess.Insert(t); err != nil {
  536. sess.Rollback()
  537. return err
  538. }
  539. // Update organization number of teams.
  540. if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil {
  541. sess.Rollback()
  542. return err
  543. }
  544. return sess.Commit()
  545. }
  546. func getTeam(e Engine, orgId int64, name string) (*Team, error) {
  547. t := &Team{
  548. OrgID: orgId,
  549. LowerName: strings.ToLower(name),
  550. }
  551. has, err := e.Get(t)
  552. if err != nil {
  553. return nil, err
  554. } else if !has {
  555. return nil, ErrTeamNotExist
  556. }
  557. return t, nil
  558. }
  559. // GetTeam returns team by given team name and organization.
  560. func GetTeam(orgId int64, name string) (*Team, error) {
  561. return getTeam(x, orgId, name)
  562. }
  563. func getTeamById(e Engine, teamId int64) (*Team, error) {
  564. t := new(Team)
  565. has, err := e.Id(teamId).Get(t)
  566. if err != nil {
  567. return nil, err
  568. } else if !has {
  569. return nil, ErrTeamNotExist
  570. }
  571. return t, nil
  572. }
  573. // GetTeamById returns team by given ID.
  574. func GetTeamById(teamId int64) (*Team, error) {
  575. return getTeamById(x, teamId)
  576. }
  577. // UpdateTeam updates information of team.
  578. func UpdateTeam(t *Team, authChanged bool) (err error) {
  579. if !IsLegalName(t.Name) {
  580. return ErrTeamNameIllegal
  581. }
  582. if len(t.Description) > 255 {
  583. t.Description = t.Description[:255]
  584. }
  585. sess := x.NewSession()
  586. defer sessionRelease(sess)
  587. if err = sess.Begin(); err != nil {
  588. return err
  589. }
  590. t.LowerName = strings.ToLower(t.Name)
  591. if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil {
  592. return fmt.Errorf("update: %v", err)
  593. }
  594. // Update access for team members if needed.
  595. if authChanged {
  596. if err = t.getRepositories(sess); err != nil {
  597. return fmt.Errorf("getRepositories:%v", err)
  598. }
  599. for _, repo := range t.Repos {
  600. if err = repo.recalculateTeamAccesses(sess, 0); err != nil {
  601. return fmt.Errorf("recalculateTeamAccesses: %v", err)
  602. }
  603. }
  604. }
  605. return sess.Commit()
  606. }
  607. // DeleteTeam deletes given team.
  608. // It's caller's responsibility to assign organization ID.
  609. func DeleteTeam(t *Team) error {
  610. if err := t.GetRepositories(); err != nil {
  611. return err
  612. }
  613. // Get organization.
  614. org, err := GetUserById(t.OrgID)
  615. if err != nil {
  616. return err
  617. }
  618. sess := x.NewSession()
  619. defer sessionRelease(sess)
  620. if err = sess.Begin(); err != nil {
  621. return err
  622. }
  623. // Delete all accesses.
  624. for _, repo := range t.Repos {
  625. if err = repo.recalculateTeamAccesses(sess, t.ID); err != nil {
  626. return err
  627. }
  628. }
  629. // Delete team-user.
  630. if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil {
  631. return err
  632. }
  633. // Delete team.
  634. if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil {
  635. return err
  636. }
  637. // Update organization number of teams.
  638. if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
  639. return err
  640. }
  641. return sess.Commit()
  642. }
  643. // ___________ ____ ___
  644. // \__ ___/___ _____ _____ | | \______ ___________
  645. // | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
  646. // | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
  647. // |____| \___ >____ /__|_| /______//____ >\___ >__|
  648. // \/ \/ \/ \/ \/
  649. // TeamUser represents an team-user relation.
  650. type TeamUser struct {
  651. ID int64 `xorm:"pk autoincr"`
  652. OrgID int64 `xorm:"INDEX"`
  653. TeamID int64 `xorm:"UNIQUE(s)"`
  654. Uid int64 `xorm:"UNIQUE(s)"`
  655. }
  656. func isTeamMember(e Engine, orgID, teamID, uid int64) bool {
  657. has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser))
  658. return has
  659. }
  660. // IsTeamMember returns true if given user is a member of team.
  661. func IsTeamMember(orgID, teamID, uid int64) bool {
  662. return isTeamMember(x, orgID, teamID, uid)
  663. }
  664. func getTeamMembers(e Engine, teamID int64) (_ []*User, err error) {
  665. teamUsers := make([]*TeamUser, 0, 10)
  666. if err = e.Where("team_id=?", teamID).Find(&teamUsers); err != nil {
  667. return nil, fmt.Errorf("get team-users: %v", err)
  668. }
  669. members := make([]*User, 0, len(teamUsers))
  670. for i := range teamUsers {
  671. member := new(User)
  672. if _, err = e.Id(teamUsers[i].Uid).Get(member); err != nil {
  673. return nil, fmt.Errorf("get user '%d': %v", teamUsers[i].Uid, err)
  674. }
  675. members = append(members, member)
  676. }
  677. return members, nil
  678. }
  679. // GetTeamMembers returns all members in given team of organization.
  680. func GetTeamMembers(teamID int64) ([]*User, error) {
  681. return getTeamMembers(x, teamID)
  682. }
  683. func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) {
  684. tus := make([]*TeamUser, 0, 5)
  685. if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil {
  686. return nil, err
  687. }
  688. ts := make([]*Team, len(tus))
  689. for i, tu := range tus {
  690. t := new(Team)
  691. has, err := e.Id(tu.TeamID).Get(t)
  692. if err != nil {
  693. return nil, err
  694. } else if !has {
  695. return nil, ErrTeamNotExist
  696. }
  697. ts[i] = t
  698. }
  699. return ts, nil
  700. }
  701. // GetUserTeams returns all teams that user belongs to in given organization.
  702. func GetUserTeams(orgId, uid int64) ([]*Team, error) {
  703. return getUserTeams(x, orgId, uid)
  704. }
  705. // AddTeamMember adds new member to given team of given organization.
  706. func AddTeamMember(orgId, teamId, uid int64) error {
  707. if IsTeamMember(orgId, teamId, uid) {
  708. return nil
  709. }
  710. if err := AddOrgUser(orgId, uid); err != nil {
  711. return err
  712. }
  713. // Get team and its repositories.
  714. t, err := GetTeamById(teamId)
  715. if err != nil {
  716. return err
  717. }
  718. t.NumMembers++
  719. if err = t.GetRepositories(); err != nil {
  720. return err
  721. }
  722. sess := x.NewSession()
  723. defer sessionRelease(sess)
  724. if err = sess.Begin(); err != nil {
  725. return err
  726. }
  727. tu := &TeamUser{
  728. Uid: uid,
  729. OrgID: orgId,
  730. TeamID: teamId,
  731. }
  732. if _, err = sess.Insert(tu); err != nil {
  733. return err
  734. } else if _, err = sess.Id(t.ID).Update(t); err != nil {
  735. return err
  736. }
  737. // Give access to team repositories.
  738. for _, repo := range t.Repos {
  739. if err = repo.recalculateTeamAccesses(sess, 0); err != nil {
  740. return err
  741. }
  742. }
  743. // We make sure it exists before.
  744. ou := new(OrgUser)
  745. if _, err = sess.Where("uid=?", uid).And("org_id=?", orgId).Get(ou); err != nil {
  746. return err
  747. }
  748. ou.NumTeams++
  749. if t.IsOwnerTeam() {
  750. ou.IsOwner = true
  751. }
  752. if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil {
  753. return err
  754. }
  755. return sess.Commit()
  756. }
  757. func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
  758. if !isTeamMember(e, orgId, teamId, uid) {
  759. return nil
  760. }
  761. // Get team and its repositories.
  762. t, err := getTeamById(e, teamId)
  763. if err != nil {
  764. return err
  765. }
  766. // Check if the user to delete is the last member in owner team.
  767. if t.IsOwnerTeam() && t.NumMembers == 1 {
  768. return ErrLastOrgOwner
  769. }
  770. t.NumMembers--
  771. if err = t.getRepositories(e); err != nil {
  772. return err
  773. }
  774. // Get organization.
  775. org, err := getUserById(e, orgId)
  776. if err != nil {
  777. return err
  778. }
  779. tu := &TeamUser{
  780. Uid: uid,
  781. OrgID: orgId,
  782. TeamID: teamId,
  783. }
  784. if _, err := e.Delete(tu); err != nil {
  785. return err
  786. } else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
  787. return err
  788. }
  789. // Delete access to team repositories.
  790. for _, repo := range t.Repos {
  791. if err = repo.recalculateTeamAccesses(e, 0); err != nil {
  792. return err
  793. }
  794. }
  795. // This must exist.
  796. ou := new(OrgUser)
  797. _, err = e.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou)
  798. if err != nil {
  799. return err
  800. }
  801. ou.NumTeams--
  802. if t.IsOwnerTeam() {
  803. ou.IsOwner = false
  804. }
  805. if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil {
  806. return err
  807. }
  808. return nil
  809. }
  810. // RemoveTeamMember removes member from given team of given organization.
  811. func RemoveTeamMember(orgId, teamId, uid int64) error {
  812. sess := x.NewSession()
  813. defer sessionRelease(sess)
  814. if err := sess.Begin(); err != nil {
  815. return err
  816. }
  817. if err := removeTeamMember(sess, orgId, teamId, uid); err != nil {
  818. return err
  819. }
  820. return sess.Commit()
  821. }
  822. // ___________ __________
  823. // \__ ___/___ _____ _____\______ \ ____ ______ ____
  824. // | |_/ __ \\__ \ / \| _// __ \\____ \ / _ \
  825. // | |\ ___/ / __ \| Y Y \ | \ ___/| |_> > <_> )
  826. // |____| \___ >____ /__|_| /____|_ /\___ > __/ \____/
  827. // \/ \/ \/ \/ \/|__|
  828. // TeamRepo represents an team-repository relation.
  829. type TeamRepo struct {
  830. ID int64 `xorm:"pk autoincr"`
  831. OrgID int64 `xorm:"INDEX"`
  832. TeamID int64 `xorm:"UNIQUE(s)"`
  833. RepoID int64 `xorm:"UNIQUE(s)"`
  834. }
  835. func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool {
  836. has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo))
  837. return has
  838. }
  839. // HasTeamRepo returns true if given repository belongs to team.
  840. func HasTeamRepo(orgID, teamID, repoID int64) bool {
  841. return hasTeamRepo(x, orgID, teamID, repoID)
  842. }
  843. func addTeamRepo(e Engine, orgID, teamID, repoID int64) error {
  844. _, err := e.InsertOne(&TeamRepo{
  845. OrgID: orgID,
  846. TeamID: teamID,
  847. RepoID: repoID,
  848. })
  849. return err
  850. }
  851. // AddTeamRepo adds new repository relation to team.
  852. func AddTeamRepo(orgID, teamID, repoID int64) error {
  853. return addTeamRepo(x, orgID, teamID, repoID)
  854. }
  855. func removeTeamRepo(e Engine, teamID, repoID int64) error {
  856. _, err := e.Delete(&TeamRepo{
  857. TeamID: teamID,
  858. RepoID: repoID,
  859. })
  860. return err
  861. }
  862. // RemoveTeamRepo deletes repository relation to team.
  863. func RemoveTeamRepo(teamID, repoID int64) error {
  864. return removeTeamRepo(x, teamID, repoID)
  865. }
  866. func removeOrgRepo(e Engine, orgID, repoID int64) error {
  867. _, err := e.Delete(&TeamRepo{
  868. OrgID: orgID,
  869. RepoID: repoID,
  870. })
  871. return err
  872. }
  873. // RemoveOrgRepo removes all team-repository relations of given organization.
  874. func RemoveOrgRepo(orgID, repoID int64) error {
  875. return removeOrgRepo(x, orgID, repoID)
  876. }