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 22 kB

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