org.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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/gogits/gogs/modules/base"
  10. )
  11. var (
  12. ErrOrgNotExist = errors.New("Organization does not exist")
  13. ErrTeamAlreadyExist = errors.New("Team already exist")
  14. ErrTeamNotExist = errors.New("Team does not exist")
  15. ErrTeamNameIllegal = errors.New("Team name contains illegal characters")
  16. ErrLastOrgOwner = errors.New("The user to remove is the last member in owner team")
  17. )
  18. // IsOrgOwner returns true if given user is in the owner team.
  19. func (org *User) IsOrgOwner(uid int64) bool {
  20. return IsOrganizationOwner(org.Id, uid)
  21. }
  22. // IsOrgMember returns true if given user is member of organization.
  23. func (org *User) IsOrgMember(uid int64) bool {
  24. return IsOrganizationMember(org.Id, uid)
  25. }
  26. // GetTeam returns named team of organization.
  27. func (org *User) GetTeam(name string) (*Team, error) {
  28. return GetTeam(org.Id, name)
  29. }
  30. // GetOwnerTeam returns owner team of organization.
  31. func (org *User) GetOwnerTeam() (*Team, error) {
  32. return org.GetTeam(OWNER_TEAM)
  33. }
  34. // GetTeams returns all teams that belong to organization.
  35. func (org *User) GetTeams() error {
  36. return x.Where("org_id=?", org.Id).Find(&org.Teams)
  37. }
  38. // GetMembers returns all members of organization.
  39. func (org *User) GetMembers() error {
  40. ous, err := GetOrgUsersByOrgId(org.Id)
  41. if err != nil {
  42. return err
  43. }
  44. org.Members = make([]*User, len(ous))
  45. for i, ou := range ous {
  46. org.Members[i], err = GetUserById(ou.Uid)
  47. if err != nil {
  48. return err
  49. }
  50. }
  51. return nil
  52. }
  53. // AddMember adds new member to organization.
  54. func (org *User) AddMember(uid int64) error {
  55. return AddOrgUser(org.Id, uid)
  56. }
  57. // RemoveMember removes member from organization.
  58. func (org *User) RemoveMember(uid int64) error {
  59. return RemoveOrgUser(org.Id, uid)
  60. }
  61. // CreateOrganization creates record of a new organization.
  62. func CreateOrganization(org, owner *User) (*User, error) {
  63. if !IsLegalName(org.Name) {
  64. return nil, ErrUserNameIllegal
  65. }
  66. isExist, err := IsUserExist(org.Name)
  67. if err != nil {
  68. return nil, err
  69. } else if isExist {
  70. return nil, ErrUserAlreadyExist
  71. }
  72. isExist, err = IsEmailUsed(org.Email)
  73. if err != nil {
  74. return nil, err
  75. } else if isExist {
  76. return nil, ErrEmailAlreadyUsed
  77. }
  78. org.LowerName = strings.ToLower(org.Name)
  79. org.FullName = org.Name
  80. org.Avatar = base.EncodeMd5(org.Email)
  81. org.AvatarEmail = org.Email
  82. // No password for organization.
  83. org.NumTeams = 1
  84. org.NumMembers = 1
  85. sess := x.NewSession()
  86. defer sess.Close()
  87. if err = sess.Begin(); err != nil {
  88. return nil, err
  89. }
  90. if _, err = sess.Insert(org); err != nil {
  91. sess.Rollback()
  92. return nil, err
  93. }
  94. if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
  95. sess.Rollback()
  96. return nil, err
  97. }
  98. // Create default owner team.
  99. t := &Team{
  100. OrgId: org.Id,
  101. LowerName: strings.ToLower(OWNER_TEAM),
  102. Name: OWNER_TEAM,
  103. Authorize: ORG_ADMIN,
  104. NumMembers: 1,
  105. }
  106. if _, err = sess.Insert(t); err != nil {
  107. sess.Rollback()
  108. return nil, err
  109. }
  110. // Add initial creator to organization and owner team.
  111. ou := &OrgUser{
  112. Uid: owner.Id,
  113. OrgId: org.Id,
  114. IsOwner: true,
  115. NumTeam: 1,
  116. }
  117. if _, err = sess.Insert(ou); err != nil {
  118. sess.Rollback()
  119. return nil, err
  120. }
  121. tu := &TeamUser{
  122. Uid: owner.Id,
  123. OrgId: org.Id,
  124. TeamId: t.Id,
  125. }
  126. if _, err = sess.Insert(tu); err != nil {
  127. sess.Rollback()
  128. return nil, err
  129. }
  130. return org, sess.Commit()
  131. }
  132. // TODO: need some kind of mechanism to record failure.
  133. // DeleteOrganization completely and permanently deletes everything of organization.
  134. func DeleteOrganization(org *User) (err error) {
  135. if err := DeleteUser(org); err != nil {
  136. return err
  137. }
  138. sess := x.NewSession()
  139. defer sess.Close()
  140. if err = sess.Begin(); err != nil {
  141. return err
  142. }
  143. if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil {
  144. sess.Rollback()
  145. return err
  146. }
  147. if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil {
  148. sess.Rollback()
  149. return err
  150. }
  151. if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil {
  152. sess.Rollback()
  153. return err
  154. }
  155. return sess.Commit()
  156. }
  157. // ________ ____ ___
  158. // \_____ \_______ ____ | | \______ ___________
  159. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  160. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  161. // \_______ /__| \___ /|______//____ >\___ >__|
  162. // \/ /_____/ \/ \/
  163. // OrgUser represents an organization-user relation.
  164. type OrgUser struct {
  165. Id int64
  166. Uid int64 `xorm:"INDEX UNIQUE(s)"`
  167. OrgId int64 `xorm:"INDEX UNIQUE(s)"`
  168. IsPublic bool
  169. IsOwner bool
  170. NumTeam int
  171. }
  172. // IsOrganizationOwner returns true if given user is in the owner team.
  173. func IsOrganizationOwner(orgId, uid int64) bool {
  174. has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  175. return has
  176. }
  177. // IsOrganizationMember returns true if given user is member of organization.
  178. func IsOrganizationMember(orgId, uid int64) bool {
  179. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
  180. return has
  181. }
  182. // IsPublicMembership returns ture if given user public his/her membership.
  183. func IsPublicMembership(orgId, uid int64) bool {
  184. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("is_public=?", true).Get(new(OrgUser))
  185. return has
  186. }
  187. // GetOrgUsersByUserId returns all organization-user relations by user ID.
  188. func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
  189. ous := make([]*OrgUser, 0, 10)
  190. err := x.Where("uid=?", uid).Find(&ous)
  191. return ous, err
  192. }
  193. // GetOrgUsersByOrgId returns all organization-user relations by organization ID.
  194. func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
  195. ous := make([]*OrgUser, 0, 10)
  196. err := x.Where("org_id=?", orgId).Find(&ous)
  197. return ous, err
  198. }
  199. // ChangeOrgUserStatus changes public or private membership status.
  200. func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
  201. ou := new(OrgUser)
  202. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  203. if err != nil {
  204. return err
  205. } else if !has {
  206. return nil
  207. }
  208. ou.IsPublic = public
  209. _, err = x.Id(ou.Id).AllCols().Update(ou)
  210. return err
  211. }
  212. // AddOrgUser adds new user to given organization.
  213. func AddOrgUser(orgId, uid int64) error {
  214. if IsOrganizationMember(orgId, uid) {
  215. return nil
  216. }
  217. ou := &OrgUser{
  218. Uid: uid,
  219. OrgId: orgId,
  220. }
  221. sess := x.NewSession()
  222. defer sess.Close()
  223. if err := sess.Begin(); err != nil {
  224. return err
  225. }
  226. if _, err := sess.Insert(ou); err != nil {
  227. sess.Rollback()
  228. return err
  229. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgId); err != nil {
  230. sess.Rollback()
  231. return err
  232. }
  233. return sess.Commit()
  234. }
  235. // RemoveOrgUser removes user from given organization.
  236. func RemoveOrgUser(orgId, uid int64) error {
  237. ou := new(OrgUser)
  238. has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
  239. if err != nil {
  240. return err
  241. } else if !has {
  242. return nil
  243. }
  244. // Check if the user to delete is the last member in owner team.
  245. if IsOrganizationOwner(orgId, uid) {
  246. org, err := GetUserById(orgId)
  247. if err != nil {
  248. return err
  249. }
  250. t, err := org.GetOwnerTeam()
  251. if err != nil {
  252. return err
  253. }
  254. if t.NumMembers == 1 {
  255. return ErrLastOrgOwner
  256. }
  257. }
  258. sess := x.NewSession()
  259. defer sess.Close()
  260. if err := sess.Begin(); err != nil {
  261. return err
  262. }
  263. if _, err := sess.Id(ou.Id).Delete(ou); err != nil {
  264. sess.Rollback()
  265. return err
  266. } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil {
  267. sess.Rollback()
  268. return err
  269. }
  270. return sess.Commit()
  271. }
  272. // ___________
  273. // \__ ___/___ _____ _____
  274. // | |_/ __ \\__ \ / \
  275. // | |\ ___/ / __ \| Y Y \
  276. // |____| \___ >____ /__|_| /
  277. // \/ \/ \/
  278. type AuthorizeType int
  279. const (
  280. ORG_READABLE AuthorizeType = iota + 1
  281. ORG_WRITABLE
  282. ORG_ADMIN
  283. )
  284. const OWNER_TEAM = "Owners"
  285. // Team represents a organization team.
  286. type Team struct {
  287. Id int64
  288. OrgId int64 `xorm:"INDEX"`
  289. LowerName string
  290. Name string
  291. Description string
  292. Authorize AuthorizeType
  293. RepoIds string `xorm:"TEXT"`
  294. NumMembers int
  295. NumRepos int
  296. Members []*User `xorm:"-"`
  297. }
  298. // IsTeamMember returns true if given user is a member of team.
  299. func (t *Team) IsMember(uid int64) bool {
  300. return IsTeamMember(t.OrgId, t.Id, uid)
  301. }
  302. // GetMembers returns all members in given team of organization.
  303. func (t *Team) GetMembers() (err error) {
  304. t.Members, err = GetTeamMembers(t.OrgId, t.Id)
  305. return err
  306. }
  307. // NewTeam creates a record of new team.
  308. // It's caller's responsibility to assign organization ID.
  309. func NewTeam(t *Team) error {
  310. if !IsLegalName(t.Name) {
  311. return ErrTeamNameIllegal
  312. }
  313. has, err := x.Id(t.OrgId).Get(new(User))
  314. if err != nil {
  315. return err
  316. } else if !has {
  317. return ErrOrgNotExist
  318. }
  319. t.LowerName = strings.ToLower(t.Name)
  320. has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
  321. if err != nil {
  322. return err
  323. } else if has {
  324. return ErrTeamAlreadyExist
  325. }
  326. sess := x.NewSession()
  327. defer sess.Close()
  328. if err = sess.Begin(); err != nil {
  329. return err
  330. }
  331. if _, err = sess.Insert(t); err != nil {
  332. sess.Rollback()
  333. return err
  334. }
  335. // Update organization number of teams.
  336. if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
  337. sess.Rollback()
  338. return err
  339. }
  340. return sess.Commit()
  341. }
  342. // GetTeam returns team by given team name and organization.
  343. func GetTeam(orgId int64, name string) (*Team, error) {
  344. t := &Team{
  345. OrgId: orgId,
  346. LowerName: strings.ToLower(name),
  347. }
  348. has, err := x.Get(t)
  349. if err != nil {
  350. return nil, err
  351. } else if !has {
  352. return nil, ErrTeamNotExist
  353. }
  354. return t, nil
  355. }
  356. // GetTeamById returns team by given ID.
  357. func GetTeamById(teamId int64) (*Team, error) {
  358. t := new(Team)
  359. has, err := x.Id(teamId).Get(t)
  360. if err != nil {
  361. return nil, err
  362. } else if !has {
  363. return nil, ErrTeamNotExist
  364. }
  365. return t, nil
  366. }
  367. // UpdateTeam updates information of team.
  368. func UpdateTeam(t *Team) error {
  369. if len(t.Description) > 255 {
  370. t.Description = t.Description[:255]
  371. }
  372. t.LowerName = strings.ToLower(t.Name)
  373. _, err := x.Id(t.Id).AllCols().Update(t)
  374. return err
  375. }
  376. // ___________ ____ ___
  377. // \__ ___/___ _____ _____ | | \______ ___________
  378. // | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
  379. // | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
  380. // |____| \___ >____ /__|_| /______//____ >\___ >__|
  381. // \/ \/ \/ \/ \/
  382. // TeamUser represents an team-user relation.
  383. type TeamUser struct {
  384. Id int64
  385. Uid int64
  386. OrgId int64 `xorm:"INDEX"`
  387. TeamId int64
  388. }
  389. // IsTeamMember returns true if given user is a member of team.
  390. func IsTeamMember(orgId, teamId, uid int64) bool {
  391. has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser))
  392. return has
  393. }
  394. // GetTeamMembers returns all members in given team of organization.
  395. func GetTeamMembers(orgId, teamId int64) ([]*User, error) {
  396. tus := make([]*TeamUser, 0, 10)
  397. err := x.Where("org_id=?", orgId).And("team_id=?", teamId).Find(&tus)
  398. if err != nil {
  399. return nil, err
  400. }
  401. us := make([]*User, len(tus))
  402. for i, tu := range tus {
  403. us[i], err = GetUserById(tu.Uid)
  404. if err != nil {
  405. return nil, err
  406. }
  407. }
  408. return us, nil
  409. }
  410. // AddTeamMember adds new member to given team of given organization.
  411. func AddTeamMember(orgId, teamId, uid int64) error {
  412. if !IsOrganizationMember(orgId, uid) || IsTeamMember(orgId, teamId, uid) {
  413. return nil
  414. }
  415. // We can use raw SQL here but we also want to vertify there is a such team.
  416. t, err := GetTeamById(teamId)
  417. if err != nil {
  418. return err
  419. }
  420. t.NumMembers++
  421. sess := x.NewSession()
  422. defer sess.Close()
  423. if err = sess.Begin(); err != nil {
  424. return err
  425. }
  426. tu := &TeamUser{
  427. Uid: uid,
  428. OrgId: orgId,
  429. TeamId: teamId,
  430. }
  431. if _, err = sess.Insert(tu); err != nil {
  432. sess.Rollback()
  433. return err
  434. } else if _, err = sess.Id(t.Id).Update(t); err != nil {
  435. sess.Rollback()
  436. return err
  437. }
  438. return sess.Commit()
  439. }
  440. // RemoveMember removes member from given team of given organization.
  441. func RemoveMember(orgId, teamId, uid int64) error {
  442. if !IsTeamMember(orgId, teamId, uid) {
  443. return nil
  444. }
  445. sess := x.NewSession()
  446. defer sess.Close()
  447. if err := sess.Begin(); err != nil {
  448. return err
  449. }
  450. tu := &TeamUser{
  451. Uid: uid,
  452. OrgId: orgId,
  453. TeamId: teamId,
  454. }
  455. if _, err := sess.Delete(tu); err != nil {
  456. sess.Rollback()
  457. return err
  458. } else if _, err = sess.Exec("UPDATE `team` SET num_members = num_members - 1 WHERE id = ?", teamId); err != nil {
  459. sess.Rollback()
  460. return err
  461. }
  462. return sess.Commit()
  463. }