org.go 21 KB

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