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 25 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
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. }