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

org.go 24 kB

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