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

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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/Unknwon/com"
  11. "github.com/go-xorm/xorm"
  12. )
  13. var (
  14. ErrOrgNotExist = errors.New("Organization does not exist")
  15. ErrTeamNotExist = errors.New("Team does not exist")
  16. )
  17. // IsOwnedBy returns true if given user is in the owner team.
  18. func (org *User) IsOwnedBy(uid int64) bool {
  19. return IsOrganizationOwner(org.Id, uid)
  20. }
  21. // IsOrgMember returns true if given user is member of organization.
  22. func (org *User) IsOrgMember(uid int64) bool {
  23. return org.IsOrganization() && IsOrganizationMember(org.Id, uid)
  24. }
  25. func (org *User) getTeam(e Engine, name string) (*Team, error) {
  26. return getTeam(e, org.Id, name)
  27. }
  28. // GetTeam returns named team of organization.
  29. func (org *User) GetTeam(name string) (*Team, error) {
  30. return org.getTeam(x, name)
  31. }
  32. func (org *User) getOwnerTeam(e Engine) (*Team, error) {
  33. return org.getTeam(e, OWNER_TEAM)
  34. }
  35. // GetOwnerTeam returns owner team of organization.
  36. func (org *User) GetOwnerTeam() (*Team, error) {
  37. return org.getOwnerTeam(x)
  38. }
  39. func (org *User) getTeams(e Engine) error {
  40. return e.Where("org_id=?", org.Id).Find(&org.Teams)
  41. }
  42. // GetTeams returns all teams that belong to organization.
  43. func (org *User) GetTeams() error {
  44. return org.getTeams(x)
  45. }
  46. // GetMembers returns all members of organization.
  47. func (org *User) GetMembers() error {
  48. ous, err := GetOrgUsersByOrgID(org.Id)
  49. if err != nil {
  50. return err
  51. }
  52. org.Members = make([]*User, len(ous))
  53. for i, ou := range ous {
  54. org.Members[i], err = GetUserByID(ou.Uid)
  55. if err != nil {
  56. return err
  57. }
  58. }
  59. return nil
  60. }
  61. // AddMember adds new member to organization.
  62. func (org *User) AddMember(uid int64) error {
  63. return AddOrgUser(org.Id, uid)
  64. }
  65. // RemoveMember removes member from organization.
  66. func (org *User) RemoveMember(uid int64) error {
  67. return RemoveOrgUser(org.Id, uid)
  68. }
  69. func (org *User) removeOrgRepo(e Engine, repoID int64) error {
  70. return removeOrgRepo(e, org.Id, repoID)
  71. }
  72. // RemoveOrgRepo removes all team-repository relations of organization.
  73. func (org *User) RemoveOrgRepo(repoID int64) error {
  74. return org.removeOrgRepo(x, repoID)
  75. }
  76. // CreateOrganization creates record of a new organization.
  77. func CreateOrganization(org, owner *User) (err error) {
  78. if err = IsUsableName(org.Name); err != nil {
  79. return err
  80. }
  81. isExist, err := IsUserExist(0, org.Name)
  82. if err != nil {
  83. return err
  84. } else if isExist {
  85. return ErrUserAlreadyExist{org.Name}
  86. }
  87. org.LowerName = strings.ToLower(org.Name)
  88. org.Rands = GetUserSalt()
  89. org.Salt = GetUserSalt()
  90. org.UseCustomAvatar = true
  91. org.MaxRepoCreation = -1
  92. org.NumTeams = 1
  93. org.NumMembers = 1
  94. sess := x.NewSession()
  95. defer sessionRelease(sess)
  96. if err = sess.Begin(); err != nil {
  97. return err
  98. }
  99. if _, err = sess.Insert(org); err != nil {
  100. return fmt.Errorf("insert organization: %v", err)
  101. }
  102. org.GenerateRandomAvatar()
  103. // Add initial creator to organization and owner team.
  104. if _, err = sess.Insert(&OrgUser{
  105. Uid: owner.Id,
  106. OrgID: org.Id,
  107. IsOwner: true,
  108. NumTeams: 1,
  109. }); err != nil {
  110. return fmt.Errorf("insert org-user relation: %v", err)
  111. }
  112. // Create default owner team.
  113. t := &Team{
  114. OrgID: org.Id,
  115. LowerName: strings.ToLower(OWNER_TEAM),
  116. Name: OWNER_TEAM,
  117. Authorize: ACCESS_MODE_OWNER,
  118. NumMembers: 1,
  119. }
  120. if _, err = sess.Insert(t); err != nil {
  121. return fmt.Errorf("insert owner team: %v", err)
  122. }
  123. if _, err = sess.Insert(&TeamUser{
  124. Uid: owner.Id,
  125. OrgID: org.Id,
  126. TeamID: t.ID,
  127. }); err != nil {
  128. return fmt.Errorf("insert team-user relation: %v", err)
  129. }
  130. if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
  131. return fmt.Errorf("create directory: %v", err)
  132. }
  133. return sess.Commit()
  134. }
  135. // GetOrgByName returns organization by given name.
  136. func GetOrgByName(name string) (*User, error) {
  137. if len(name) == 0 {
  138. return nil, ErrOrgNotExist
  139. }
  140. u := &User{
  141. LowerName: strings.ToLower(name),
  142. Type: USER_TYPE_ORGANIZATION,
  143. }
  144. has, err := x.Get(u)
  145. if err != nil {
  146. return nil, err
  147. } else if !has {
  148. return nil, ErrOrgNotExist
  149. }
  150. return u, nil
  151. }
  152. // CountOrganizations returns number of organizations.
  153. func CountOrganizations() int64 {
  154. count, _ := x.Where("type=1").Count(new(User))
  155. return count
  156. }
  157. // Organizations returns number of organizations in given page.
  158. func Organizations(page, pageSize int) ([]*User, error) {
  159. orgs := make([]*User, 0, pageSize)
  160. return orgs, x.Limit(pageSize, (page-1)*pageSize).Where("type=1").Asc("id").Find(&orgs)
  161. }
  162. // DeleteOrganization completely and permanently deletes everything of organization.
  163. func DeleteOrganization(org *User) (err error) {
  164. if err := DeleteUser(org); err != nil {
  165. return err
  166. }
  167. sess := x.NewSession()
  168. defer sessionRelease(sess)
  169. if err = sess.Begin(); err != nil {
  170. return err
  171. }
  172. if err = deleteBeans(sess,
  173. &Team{OrgID: org.Id},
  174. &OrgUser{OrgID: org.Id},
  175. &TeamUser{OrgID: org.Id},
  176. ); err != nil {
  177. return fmt.Errorf("deleteBeans: %v", err)
  178. }
  179. if err = deleteUser(sess, org); err != nil {
  180. return fmt.Errorf("deleteUser: %v", err)
  181. }
  182. return sess.Commit()
  183. }
  184. // ________ ____ ___
  185. // \_____ \_______ ____ | | \______ ___________
  186. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  187. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  188. // \_______ /__| \___ /|______//____ >\___ >__|
  189. // \/ /_____/ \/ \/
  190. // OrgUser represents an organization-user relation.
  191. type OrgUser struct {
  192. ID int64 `xorm:"pk autoincr"`
  193. Uid int64 `xorm:"INDEX UNIQUE(s)"`
  194. OrgID int64 `xorm:"INDEX UNIQUE(s)"`
  195. IsPublic bool
  196. IsOwner bool
  197. NumTeams int
  198. }
  199. // IsOrganizationOwner returns true if given user is in the owner team.
  200. func IsOrganizationOwner(orgId, uid int64) bool {
  201. has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  202. return has
  203. }
  204. // IsOrganizationMember returns true if given user is member of organization.
  205. func IsOrganizationMember(orgId, uid int64) bool {
  206. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  207. return has
  208. }
  209. // IsPublicMembership returns true if given user public his/her membership.
  210. func IsPublicMembership(orgId, uid int64) bool {
  211. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("is_public=?", true).Get(new(OrgUser))
  212. return has
  213. }
  214. func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
  215. orgs := make([]*User, 0, 10)
  216. if !showAll {
  217. sess.And("`org_user`.is_public=?", true)
  218. }
  219. return orgs, sess.And("`org_user`.uid=?", userID).
  220. Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
  221. }
  222. // GetOrgsByUserID returns a list of organizations that the given user ID
  223. // has joined.
  224. func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
  225. return getOrgsByUserID(x.NewSession(), userID, showAll)
  226. }
  227. // GetOrgsByUserIDDesc returns a list of organizations that the given user ID
  228. // has joined, ordered descending by the given condition.
  229. func GetOrgsByUserIDDesc(userID int64, desc string, showAll bool) ([]*User, error) {
  230. return getOrgsByUserID(x.NewSession().Desc(desc), userID, showAll)
  231. }
  232. func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
  233. orgs := make([]*User, 0, 10)
  234. return orgs, sess.Where("`org_user`.uid=?", userID).And("`org_user`.is_owner=?", true).
  235. Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
  236. }
  237. // GetOwnedOrgsByUserID returns a list of organizations are owned by given user ID.
  238. func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
  239. sess := x.NewSession()
  240. return getOwnedOrgsByUserID(sess, userID)
  241. }
  242. // GetOwnedOrganizationsByUserIDDesc returns a list of organizations are owned by
  243. // given user ID, ordered descending by the given condition.
  244. func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
  245. sess := x.NewSession()
  246. return getOwnedOrgsByUserID(sess.Desc(desc), userID)
  247. }
  248. // GetOrgUsersByUserID returns all organization-user relations by user ID.
  249. func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
  250. ous := make([]*OrgUser, 0, 10)
  251. sess := x.Where("uid=?", uid)
  252. if !all {
  253. // Only show public organizations
  254. sess.And("is_public=?", true)
  255. }
  256. err := sess.Find(&ous)
  257. return ous, err
  258. }
  259. // GetOrgUsersByOrgID returns all organization-user relations by organization ID.
  260. func GetOrgUsersByOrgID(orgID int64) ([]*OrgUser, error) {
  261. ous := make([]*OrgUser, 0, 10)
  262. err := x.Where("org_id=?", orgID).Find(&ous)
  263. return ous, err
  264. }
  265. // ChangeOrgUserStatus changes public or private membership status.
  266. func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
  267. ou := new(OrgUser)
  268. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  269. if err != nil {
  270. return err
  271. } else if !has {
  272. return nil
  273. }
  274. ou.IsPublic = public
  275. _, err = x.Id(ou.ID).AllCols().Update(ou)
  276. return err
  277. }
  278. // AddOrgUser adds new user to given organization.
  279. func AddOrgUser(orgId, uid int64) error {
  280. if IsOrganizationMember(orgId, uid) {
  281. return nil
  282. }
  283. sess := x.NewSession()
  284. defer sess.Close()
  285. if err := sess.Begin(); err != nil {
  286. return err
  287. }
  288. ou := &OrgUser{
  289. Uid: uid,
  290. OrgID: orgId,
  291. }
  292. if _, err := sess.Insert(ou); err != nil {
  293. sess.Rollback()
  294. return err
  295. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgId); err != nil {
  296. sess.Rollback()
  297. return err
  298. }
  299. return sess.Commit()
  300. }
  301. // RemoveOrgUser removes user from given organization.
  302. func RemoveOrgUser(orgId, uid int64) error {
  303. ou := new(OrgUser)
  304. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  305. if err != nil {
  306. return fmt.Errorf("get org-user: %v", err)
  307. } else if !has {
  308. return nil
  309. }
  310. u, err := GetUserByID(uid)
  311. if err != nil {
  312. return fmt.Errorf("GetUserById: %v", err)
  313. }
  314. org, err := GetUserByID(orgId)
  315. if err != nil {
  316. return fmt.Errorf("get organization: %v", err)
  317. } else if err = org.GetRepositories(); err != nil {
  318. return fmt.Errorf("GetRepositories: %v", err)
  319. }
  320. // Check if the user to delete is the last member in owner team.
  321. if IsOrganizationOwner(orgId, uid) {
  322. t, err := org.GetOwnerTeam()
  323. if err != nil {
  324. return err
  325. }
  326. if t.NumMembers == 1 {
  327. return ErrLastOrgOwner{UID: uid}
  328. }
  329. }
  330. sess := x.NewSession()
  331. defer sessionRelease(sess)
  332. if err := sess.Begin(); err != nil {
  333. return err
  334. }
  335. if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
  336. return err
  337. } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgId); err != nil {
  338. return err
  339. }
  340. // Delete all repository accesses.
  341. access := &Access{UserID: u.Id}
  342. for _, repo := range org.Repos {
  343. access.RepoID = repo.ID
  344. if _, err = sess.Delete(access); err != nil {
  345. return err
  346. } else if err = watchRepo(sess, u.Id, repo.ID, false); err != nil {
  347. return err
  348. }
  349. }
  350. // Delete member in his/her teams.
  351. teams, err := getUserTeams(sess, org.Id, u.Id)
  352. if err != nil {
  353. return err
  354. }
  355. for _, t := range teams {
  356. if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
  357. return err
  358. }
  359. }
  360. return sess.Commit()
  361. }
  362. func removeOrgRepo(e Engine, orgID, repoID int64) error {
  363. _, err := e.Delete(&TeamRepo{
  364. OrgID: orgID,
  365. RepoID: repoID,
  366. })
  367. return err
  368. }
  369. // RemoveOrgRepo removes all team-repository relations of given organization.
  370. func RemoveOrgRepo(orgID, repoID int64) error {
  371. return removeOrgRepo(x, orgID, repoID)
  372. }
  373. // GetUserRepositories gets all repositories of an organization,
  374. // that the user with the given userID has access to.
  375. func (org *User) GetUserRepositories(userID int64) (err error) {
  376. teams := make([]*Team, 0, org.NumTeams)
  377. if err = x.Sql(`SELECT team.id FROM team
  378. INNER JOIN team_user ON team_user.team_id = team.id
  379. WHERE team_user.org_id = ? AND team_user.uid = ?`, org.Id, userID).Find(&teams); err != nil {
  380. return fmt.Errorf("get teams: %v", err)
  381. }
  382. teamIDs := make([]string, len(teams))
  383. for i := range teams {
  384. teamIDs[i] = com.ToStr(teams[i].ID)
  385. }
  386. if len(teamIDs) == 0 {
  387. // user has no team but "IN ()" is invalid SQL
  388. teamIDs = append(teamIDs, "-1") // there is no repo with id=-1
  389. }
  390. repos := make([]*Repository, 0, 5)
  391. if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
  392. INNER JOIN team_repo ON team_repo.repo_id = repository.id
  393. WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
  394. GROUP BY repository.id`, strings.Join(teamIDs, ",")), org.Id, false).Find(&repos); err != nil {
  395. return fmt.Errorf("get repositories: %v", err)
  396. }
  397. org.Repos = repos
  398. // FIXME: should I change this value inside method,
  399. // or only in location of caller where it's really needed?
  400. org.NumRepos = len(org.Repos)
  401. return nil
  402. }
  403. // GetTeams returns all teams that belong to organization,
  404. // and that the user has joined.
  405. func (org *User) GetUserTeams(userID int64) error {
  406. teams := make([]*Team, 0, 5)
  407. if err := x.Sql(`SELECT team.* FROM team
  408. INNER JOIN team_user ON team_user.team_id = team.id
  409. WHERE team_user.org_id = ? AND team_user.uid = ?`,
  410. org.Id, userID).Find(&teams); err != nil {
  411. return fmt.Errorf("get teams: %v", err)
  412. }
  413. org.Teams = teams
  414. // FIXME: should I change this value inside method,
  415. // or only in location of caller where it's really needed?
  416. org.NumTeams = len(org.Teams)
  417. return nil
  418. }