You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

user.go 15KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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. "crypto/sha256"
  7. "encoding/hex"
  8. "errors"
  9. "fmt"
  10. "os"
  11. "path/filepath"
  12. "strings"
  13. "time"
  14. "github.com/gogits/git"
  15. "github.com/gogits/gogs/modules/base"
  16. "github.com/gogits/gogs/modules/log"
  17. "github.com/gogits/gogs/modules/setting"
  18. )
  19. type UserType int
  20. const (
  21. INDIVIDUAL UserType = iota // Historic reason to make it starts at 0.
  22. ORGANIZATION
  23. )
  24. var (
  25. ErrUserOwnRepos = errors.New("User still have ownership of repositories")
  26. ErrUserAlreadyExist = errors.New("User already exist")
  27. ErrUserNotExist = errors.New("User does not exist")
  28. ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
  29. ErrEmailAlreadyUsed = errors.New("E-mail already used")
  30. ErrUserNameIllegal = errors.New("User name contains illegal characters")
  31. ErrLoginSourceNotExist = errors.New("Login source does not exist")
  32. ErrLoginSourceNotActived = errors.New("Login source is not actived")
  33. ErrUnsupportedLoginType = errors.New("Login source is unknown")
  34. )
  35. // User represents the object of individual and member of organization.
  36. type User struct {
  37. Id int64
  38. LowerName string `xorm:"unique not null"`
  39. Name string `xorm:"unique not null"`
  40. FullName string
  41. Email string `xorm:"unique not null"`
  42. Passwd string `xorm:"not null"`
  43. LoginType LoginType
  44. LoginSource int64 `xorm:"not null default 0"`
  45. LoginName string
  46. Type UserType
  47. Orgs []*User `xorm:"-"`
  48. NumFollowers int
  49. NumFollowings int
  50. NumStars int
  51. NumRepos int
  52. Avatar string `xorm:"varchar(2048) not null"`
  53. AvatarEmail string `xorm:"not null"`
  54. Location string
  55. Website string
  56. IsActive bool
  57. IsAdmin bool
  58. Rands string `xorm:"VARCHAR(10)"`
  59. Salt string `xorm:"VARCHAR(10)"`
  60. Created time.Time `xorm:"created"`
  61. Updated time.Time `xorm:"updated"`
  62. // For organization.
  63. NumTeams int
  64. NumMembers int
  65. }
  66. // HomeLink returns the user home page link.
  67. func (u *User) HomeLink() string {
  68. return "/user/" + u.Name
  69. }
  70. // AvatarLink returns user gravatar link.
  71. func (u *User) AvatarLink() string {
  72. if setting.DisableGravatar {
  73. return "/img/avatar_default.jpg"
  74. } else if setting.Service.EnableCacheAvatar {
  75. return "/avatar/" + u.Avatar
  76. }
  77. return "//1.gravatar.com/avatar/" + u.Avatar
  78. }
  79. // NewGitSig generates and returns the signature of given user.
  80. func (u *User) NewGitSig() *git.Signature {
  81. return &git.Signature{
  82. Name: u.Name,
  83. Email: u.Email,
  84. When: time.Now(),
  85. }
  86. }
  87. // EncodePasswd encodes password to safe format.
  88. func (u *User) EncodePasswd() {
  89. newPasswd := base.PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
  90. u.Passwd = fmt.Sprintf("%x", newPasswd)
  91. }
  92. func (u *User) IsOrganization() bool {
  93. return u.Type == ORGANIZATION
  94. }
  95. func (u *User) GetOrganizations() error {
  96. ous, err := GetOrgUsersByUserId(u.Id)
  97. if err != nil {
  98. return err
  99. }
  100. u.Orgs = make([]*User, len(ous))
  101. for i, ou := range ous {
  102. u.Orgs[i], err = GetUserById(ou.OrgId)
  103. if err != nil {
  104. return err
  105. }
  106. }
  107. return nil
  108. }
  109. // GetOwnerTeam returns owner team of organization.
  110. func (org *User) GetOwnerTeam() (*Team, error) {
  111. t := &Team{
  112. OrgId: org.Id,
  113. Name: OWNER_TEAM,
  114. }
  115. _, err := x.Get(t)
  116. return t, err
  117. }
  118. // IsUserExist checks if given user name exist,
  119. // the user name should be noncased unique.
  120. func IsUserExist(name string) (bool, error) {
  121. if len(name) == 0 {
  122. return false, nil
  123. }
  124. return x.Get(&User{LowerName: strings.ToLower(name)})
  125. }
  126. // IsEmailUsed returns true if the e-mail has been used.
  127. func IsEmailUsed(email string) (bool, error) {
  128. if len(email) == 0 {
  129. return false, nil
  130. }
  131. return x.Get(&User{Email: email})
  132. }
  133. // GetUserSalt returns a user salt token
  134. func GetUserSalt() string {
  135. return base.GetRandomString(10)
  136. }
  137. // CreateUser creates record of a new user.
  138. func CreateUser(u *User) (*User, error) {
  139. if !IsLegalName(u.Name) {
  140. return nil, ErrUserNameIllegal
  141. }
  142. isExist, err := IsUserExist(u.Name)
  143. if err != nil {
  144. return nil, err
  145. } else if isExist {
  146. return nil, ErrUserAlreadyExist
  147. }
  148. isExist, err = IsEmailUsed(u.Email)
  149. if err != nil {
  150. return nil, err
  151. } else if isExist {
  152. return nil, ErrEmailAlreadyUsed
  153. }
  154. u.LowerName = strings.ToLower(u.Name)
  155. u.Avatar = base.EncodeMd5(u.Email)
  156. u.AvatarEmail = u.Email
  157. u.Rands = GetUserSalt()
  158. u.Salt = GetUserSalt()
  159. u.EncodePasswd()
  160. sess := x.NewSession()
  161. defer sess.Close()
  162. if err = sess.Begin(); err != nil {
  163. return nil, err
  164. }
  165. if _, err = sess.Insert(u); err != nil {
  166. sess.Rollback()
  167. return nil, err
  168. }
  169. if err = os.MkdirAll(UserPath(u.Name), os.ModePerm); err != nil {
  170. sess.Rollback()
  171. return nil, err
  172. }
  173. if err = sess.Commit(); err != nil {
  174. return nil, err
  175. }
  176. // Auto-set admin for user whose ID is 1.
  177. if u.Id == 1 {
  178. u.IsAdmin = true
  179. u.IsActive = true
  180. _, err = x.Id(u.Id).UseBool().Update(u)
  181. }
  182. return u, err
  183. }
  184. // CreateOrganization creates record of a new organization.
  185. func CreateOrganization(org, owner *User) (*User, error) {
  186. if !IsLegalName(org.Name) {
  187. return nil, ErrUserNameIllegal
  188. }
  189. isExist, err := IsUserExist(org.Name)
  190. if err != nil {
  191. return nil, err
  192. } else if isExist {
  193. return nil, ErrUserAlreadyExist
  194. }
  195. isExist, err = IsEmailUsed(org.Email)
  196. if err != nil {
  197. return nil, err
  198. } else if isExist {
  199. return nil, ErrEmailAlreadyUsed
  200. }
  201. org.LowerName = strings.ToLower(org.Name)
  202. org.Avatar = base.EncodeMd5(org.Email)
  203. org.AvatarEmail = org.Email
  204. // No password for organization.
  205. org.NumTeams = 1
  206. org.NumMembers = 1
  207. sess := x.NewSession()
  208. defer sess.Close()
  209. if err = sess.Begin(); err != nil {
  210. return nil, err
  211. }
  212. if _, err = sess.Insert(org); err != nil {
  213. sess.Rollback()
  214. return nil, err
  215. }
  216. // Create default owner team.
  217. t := &Team{
  218. OrgId: org.Id,
  219. Name: OWNER_TEAM,
  220. Authorize: ORG_ADMIN,
  221. NumMembers: 1,
  222. }
  223. if _, err = sess.Insert(t); err != nil {
  224. sess.Rollback()
  225. return nil, err
  226. }
  227. // Add initial creator to organization and owner team.
  228. ou := &OrgUser{
  229. Uid: owner.Id,
  230. OrgId: org.Id,
  231. IsOwner: true,
  232. NumTeam: 1,
  233. }
  234. if _, err = sess.Insert(ou); err != nil {
  235. sess.Rollback()
  236. return nil, err
  237. }
  238. tu := &TeamUser{
  239. Uid: owner.Id,
  240. OrgId: org.Id,
  241. TeamId: t.Id,
  242. }
  243. if _, err = sess.Insert(tu); err != nil {
  244. sess.Rollback()
  245. return nil, err
  246. }
  247. return org, sess.Commit()
  248. }
  249. // GetUsers returns given number of user objects with offset.
  250. func GetUsers(num, offset int) ([]User, error) {
  251. users := make([]User, 0, num)
  252. err := x.Limit(num, offset).Asc("id").Find(&users)
  253. return users, err
  254. }
  255. // get user by erify code
  256. func getVerifyUser(code string) (user *User) {
  257. if len(code) <= base.TimeLimitCodeLength {
  258. return nil
  259. }
  260. // use tail hex username query user
  261. hexStr := code[base.TimeLimitCodeLength:]
  262. if b, err := hex.DecodeString(hexStr); err == nil {
  263. if user, err = GetUserByName(string(b)); user != nil {
  264. return user
  265. }
  266. log.Error("user.getVerifyUser: %v", err)
  267. }
  268. return nil
  269. }
  270. // verify active code when active account
  271. func VerifyUserActiveCode(code string) (user *User) {
  272. minutes := setting.Service.ActiveCodeLives
  273. if user = getVerifyUser(code); user != nil {
  274. // time limit code
  275. prefix := code[:base.TimeLimitCodeLength]
  276. data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands
  277. if base.VerifyTimeLimitCode(data, minutes, prefix) {
  278. return user
  279. }
  280. }
  281. return nil
  282. }
  283. // ChangeUserName changes all corresponding setting from old user name to new one.
  284. func ChangeUserName(user *User, newUserName string) (err error) {
  285. newUserName = strings.ToLower(newUserName)
  286. // Update accesses of user.
  287. accesses := make([]Access, 0, 10)
  288. if err = x.Find(&accesses, &Access{UserName: user.LowerName}); err != nil {
  289. return err
  290. }
  291. sess := x.NewSession()
  292. defer sess.Close()
  293. if err = sess.Begin(); err != nil {
  294. return err
  295. }
  296. for i := range accesses {
  297. accesses[i].UserName = newUserName
  298. if strings.HasPrefix(accesses[i].RepoName, user.LowerName+"/") {
  299. accesses[i].RepoName = strings.Replace(accesses[i].RepoName, user.LowerName, newUserName, 1)
  300. }
  301. if err = UpdateAccessWithSession(sess, &accesses[i]); err != nil {
  302. return err
  303. }
  304. }
  305. repos, err := GetRepositories(user.Id, true)
  306. if err != nil {
  307. return err
  308. }
  309. for i := range repos {
  310. accesses = make([]Access, 0, 10)
  311. // Update accesses of user repository.
  312. if err = x.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repos[i].LowerName}); err != nil {
  313. return err
  314. }
  315. for j := range accesses {
  316. accesses[j].UserName = newUserName
  317. accesses[j].RepoName = newUserName + "/" + repos[i].LowerName
  318. if err = UpdateAccessWithSession(sess, &accesses[j]); err != nil {
  319. return err
  320. }
  321. }
  322. }
  323. // Change user directory name.
  324. if err = os.Rename(UserPath(user.LowerName), UserPath(newUserName)); err != nil {
  325. sess.Rollback()
  326. return err
  327. }
  328. return sess.Commit()
  329. }
  330. // UpdateUser updates user's information.
  331. func UpdateUser(u *User) (err error) {
  332. u.LowerName = strings.ToLower(u.Name)
  333. if len(u.Location) > 255 {
  334. u.Location = u.Location[:255]
  335. }
  336. if len(u.Website) > 255 {
  337. u.Website = u.Website[:255]
  338. }
  339. _, err = x.Id(u.Id).AllCols().Update(u)
  340. return err
  341. }
  342. // DeleteUser completely deletes everything of the user.
  343. func DeleteUser(user *User) error {
  344. // Check ownership of repository.
  345. count, err := GetRepositoryCount(user)
  346. if err != nil {
  347. return errors.New("modesl.GetRepositories: " + err.Error())
  348. } else if count > 0 {
  349. return ErrUserOwnRepos
  350. }
  351. // TODO: check issues, other repos' commits
  352. // Delete all followers.
  353. if _, err = x.Delete(&Follow{FollowId: user.Id}); err != nil {
  354. return err
  355. }
  356. // Delete oauth2.
  357. if _, err = x.Delete(&Oauth2{Uid: user.Id}); err != nil {
  358. return err
  359. }
  360. // Delete all feeds.
  361. if _, err = x.Delete(&Action{UserId: user.Id}); err != nil {
  362. return err
  363. }
  364. // Delete all watches.
  365. if _, err = x.Delete(&Watch{UserId: user.Id}); err != nil {
  366. return err
  367. }
  368. // Delete all accesses.
  369. if _, err = x.Delete(&Access{UserName: user.LowerName}); err != nil {
  370. return err
  371. }
  372. // Delete all SSH keys.
  373. keys := make([]*PublicKey, 0, 10)
  374. if err = x.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil {
  375. return err
  376. }
  377. for _, key := range keys {
  378. if err = DeletePublicKey(key); err != nil {
  379. return err
  380. }
  381. }
  382. // Delete user directory.
  383. if err = os.RemoveAll(UserPath(user.Name)); err != nil {
  384. return err
  385. }
  386. _, err = x.Delete(user)
  387. return err
  388. }
  389. // DeleteInactivateUsers deletes all inactivate users.
  390. func DeleteInactivateUsers() error {
  391. _, err := x.Where("is_active=?", false).Delete(new(User))
  392. return err
  393. }
  394. // UserPath returns the path absolute path of user repositories.
  395. func UserPath(userName string) string {
  396. return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
  397. }
  398. func GetUserByKeyId(keyId int64) (*User, error) {
  399. user := new(User)
  400. rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?"
  401. has, err := x.Sql(rawSql, keyId).Get(user)
  402. if err != nil {
  403. return nil, err
  404. } else if !has {
  405. return nil, ErrUserNotKeyOwner
  406. }
  407. return user, nil
  408. }
  409. // GetUserById returns the user object by given ID if exists.
  410. func GetUserById(id int64) (*User, error) {
  411. u := new(User)
  412. has, err := x.Id(id).Get(u)
  413. if err != nil {
  414. return nil, err
  415. } else if !has {
  416. return nil, ErrUserNotExist
  417. }
  418. return u, nil
  419. }
  420. // GetUserByName returns the user object by given name if exists.
  421. func GetUserByName(name string) (*User, error) {
  422. if len(name) == 0 {
  423. return nil, ErrUserNotExist
  424. }
  425. user := &User{LowerName: strings.ToLower(name)}
  426. has, err := x.Get(user)
  427. if err != nil {
  428. return nil, err
  429. } else if !has {
  430. return nil, ErrUserNotExist
  431. }
  432. return user, nil
  433. }
  434. // GetUserEmailsByNames returns a slice of e-mails corresponds to names.
  435. func GetUserEmailsByNames(names []string) []string {
  436. mails := make([]string, 0, len(names))
  437. for _, name := range names {
  438. u, err := GetUserByName(name)
  439. if err != nil {
  440. continue
  441. }
  442. mails = append(mails, u.Email)
  443. }
  444. return mails
  445. }
  446. // GetUserIdsByNames returns a slice of ids corresponds to names.
  447. func GetUserIdsByNames(names []string) []int64 {
  448. ids := make([]int64, 0, len(names))
  449. for _, name := range names {
  450. u, err := GetUserByName(name)
  451. if err != nil {
  452. continue
  453. }
  454. ids = append(ids, u.Id)
  455. }
  456. return ids
  457. }
  458. // GetUserByEmail returns the user object by given e-mail if exists.
  459. func GetUserByEmail(email string) (*User, error) {
  460. if len(email) == 0 {
  461. return nil, ErrUserNotExist
  462. }
  463. user := &User{Email: strings.ToLower(email)}
  464. has, err := x.Get(user)
  465. if err != nil {
  466. return nil, err
  467. } else if !has {
  468. return nil, ErrUserNotExist
  469. }
  470. return user, nil
  471. }
  472. // SearchUserByName returns given number of users whose name contains keyword.
  473. func SearchUserByName(key string, limit int) (us []*User, err error) {
  474. // Prevent SQL inject.
  475. key = strings.TrimSpace(key)
  476. if len(key) == 0 {
  477. return us, nil
  478. }
  479. key = strings.Split(key, " ")[0]
  480. if len(key) == 0 {
  481. return us, nil
  482. }
  483. key = strings.ToLower(key)
  484. us = make([]*User, 0, limit)
  485. err = x.Limit(limit).Where("lower_name like '%" + key + "%'").Find(&us)
  486. return us, err
  487. }
  488. // Follow is connection request for receiving user notifycation.
  489. type Follow struct {
  490. Id int64
  491. UserId int64 `xorm:"unique(follow)"`
  492. FollowId int64 `xorm:"unique(follow)"`
  493. }
  494. // FollowUser marks someone be another's follower.
  495. func FollowUser(userId int64, followId int64) (err error) {
  496. session := x.NewSession()
  497. defer session.Close()
  498. session.Begin()
  499. if _, err = session.Insert(&Follow{UserId: userId, FollowId: followId}); err != nil {
  500. session.Rollback()
  501. return err
  502. }
  503. rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?"
  504. if _, err = session.Exec(rawSql, followId); err != nil {
  505. session.Rollback()
  506. return err
  507. }
  508. rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?"
  509. if _, err = session.Exec(rawSql, userId); err != nil {
  510. session.Rollback()
  511. return err
  512. }
  513. return session.Commit()
  514. }
  515. // UnFollowUser unmarks someone be another's follower.
  516. func UnFollowUser(userId int64, unFollowId int64) (err error) {
  517. session := x.NewSession()
  518. defer session.Close()
  519. session.Begin()
  520. if _, err = session.Delete(&Follow{UserId: userId, FollowId: unFollowId}); err != nil {
  521. session.Rollback()
  522. return err
  523. }
  524. rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?"
  525. if _, err = session.Exec(rawSql, unFollowId); err != nil {
  526. session.Rollback()
  527. return err
  528. }
  529. rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?"
  530. if _, err = session.Exec(rawSql, userId); err != nil {
  531. session.Rollback()
  532. return err
  533. }
  534. return session.Commit()
  535. }