permissions.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package common
  2. import (
  3. "database/sql"
  4. "devel.mephi.ru/dyokunev/cps-api/app/common/db"
  5. models "devel.mephi.ru/dyokunev/cps-models"
  6. acdir "devel.mephi.ru/dyokunev/go-acdir"
  7. asuModels "devel.mephi.ru/dyokunev/go-asu-models"
  8. helpers "devel.mephi.ru/dyokunev/go-helpers"
  9. mysqlDriver "github.com/go-sql-driver/mysql"
  10. "github.com/revel/revel"
  11. "strconv"
  12. "strings"
  13. "sync"
  14. "time"
  15. )
  16. type Permissions struct {
  17. IsFixOk bool
  18. IsFullAccess bool
  19. IsVoip bool
  20. HeadedUnits asuModels.Units
  21. AllowedUnits asuModels.Units
  22. AllowedPeople asuModels.People
  23. }
  24. var (
  25. userInfoMap = map[string]UserInfo{}
  26. userInfoMapMutex = &sync.Mutex{}
  27. getUserInfoMutex = &sync.Mutex{}
  28. )
  29. func InitUserInfo() {
  30. go func() {
  31. for {
  32. userInfoMapMutex.Lock()
  33. userInfoMap = map[string]UserInfo{}
  34. userInfoMapMutex.Unlock()
  35. time.Sleep(time.Minute * 5)
  36. }
  37. }()
  38. }
  39. func DownloadUserInfo(username string) UserInfo {
  40. var info UserInfo
  41. info.Username = strings.ToLower(username)
  42. ldapEntry, err := acdir.GetEntryByUsername(username)
  43. if err == nil {
  44. if ldapEntry.EmpGUID == 0 {
  45. //panic("ldapEntry.EmpGUID == 0")
  46. return info
  47. }
  48. info.EmpGUID = ldapEntry.EmpGUID
  49. info.Permissions.HeadedUnits = asuModels.GetUnitsHeadedBy(info.EmpGUID)
  50. info.Permissions.HeadedUnits.DoRecursive(func(unit *asuModels.Unit, argI interface{}) bool {
  51. info.Permissions.AllowedUnits = append(info.Permissions.AllowedUnits, *unit)
  52. return true
  53. }, nil)
  54. info.Permissions.AllowedPeople = info.Permissions.AllowedUnits.PrepareFormulars(true, false).GetFormulars().PreparePeople().GetPeople()
  55. me, err := asuModels.PersonSQL.First(asuModels.Person{EmpGUID: info.EmpGUID})
  56. if err != nil {
  57. panic(err)
  58. }
  59. info.Permissions.AllowedPeople = append(info.Permissions.AllowedPeople, me)
  60. } else {
  61. if err != acdir.ErrNoRows {
  62. panic(err)
  63. }
  64. }
  65. cpsUser, err := models.CpsUserSQL.First(models.CpsUser{Username: username})
  66. for err == mysqlDriver.ErrInvalidConn { // TODO: remove this hacky workaround. ATM, it solved floating bug: "invalid connection"
  67. cpsUser, err = models.CpsUserSQL.First(models.CpsUser{Username: username})
  68. }
  69. if err != nil && err != sql.ErrNoRows {
  70. panic(err)
  71. }
  72. if err == nil {
  73. info.Permissions = AppendPermissions(cpsUser, info.Permissions)
  74. }
  75. // Checking if the user has full access. In this case it's recommended to disable filters in app/controllers/controller.go:Controller.init()
  76. {
  77. rows, err := db.Sdapi1Raw.Query("SELECT COUNT(*) FROM unit")
  78. if err != nil {
  79. panic(err)
  80. }
  81. defer rows.Close()
  82. if !rows.Next() {
  83. panic("This shouldn't happend")
  84. }
  85. var unitsCount int
  86. err = rows.Scan(&unitsCount)
  87. if err != nil {
  88. panic(err)
  89. }
  90. if len(info.Permissions.AllowedUnits) > unitsCount {
  91. panic("This shouldn't happend")
  92. }
  93. if len(info.Permissions.AllowedUnits) == unitsCount {
  94. info.Permissions.IsFullAccess = true
  95. }
  96. }
  97. return info
  98. }
  99. func GetUserInfo(username string) UserInfo {
  100. getUserInfoMutex.Lock()
  101. defer func() { getUserInfoMutex.Unlock() }()
  102. username = strings.ToLower(username)
  103. userInfoMapMutex.Lock()
  104. info := userInfoMap[username]
  105. userInfoMapMutex.Unlock()
  106. if info.Username != username {
  107. info = DownloadUserInfo(username)
  108. userInfoMapMutex.Lock()
  109. userInfoMap[username] = info
  110. userInfoMapMutex.Unlock()
  111. }
  112. return info
  113. }
  114. func AppendPermissions(cpsUser models.CpsUser, permissions Permissions) Permissions {
  115. alreadySetUnitIds := map[int]bool{}
  116. for _, unit := range permissions.AllowedUnits {
  117. alreadySetUnitIds[unit.Id] = true
  118. }
  119. if cpsUser.UnitCodePatternsStr != nil {
  120. *cpsUser.UnitCodePatternsStr = strings.Replace(helpers.RemoveAllStringByPattern(*cpsUser.UnitCodePatternsStr, "[^0-9%*]+"), "*", "%", -1)
  121. if len(*cpsUser.UnitCodePatternsStr) > 0 {
  122. unitCodePatterns := strings.Split(*cpsUser.UnitCodePatternsStr, ",")
  123. for _, pattern := range unitCodePatterns {
  124. if pattern == "%" {
  125. var err error
  126. permissions.AllowedUnits, err = asuModels.UnitSQL.Select()
  127. if err != nil {
  128. panic(err)
  129. }
  130. permissions.AllowedPeople, err = asuModels.PersonSQL.Select()
  131. if err != nil {
  132. panic(err)
  133. }
  134. continue
  135. }
  136. pattern = "1" + pattern
  137. var units asuModels.Units
  138. units, err := asuModels.UnitSQL.ActiveOnly().Select("Code LIKE ?", pattern)
  139. if err != nil {
  140. panic(err)
  141. }
  142. units.PrepareChildrenTree().DoRecursive(func(unit *asuModels.Unit, argI interface{}) bool {
  143. if alreadySetUnitIds[unit.Id] {
  144. return true
  145. }
  146. permissions.AllowedUnits = append(permissions.AllowedUnits, *unit)
  147. permissions.AllowedPeople = append(permissions.AllowedPeople, unit.PrepareFormulars().GetFormulars().PreparePeople().GetPeople()...)
  148. return true
  149. }, nil)
  150. }
  151. }
  152. }
  153. for _, unit := range permissions.AllowedUnits {
  154. alreadySetUnitIds[unit.Id] = true
  155. }
  156. if cpsUser.EmpGUIDsStr != nil {
  157. *cpsUser.EmpGUIDsStr = helpers.RemoveAllStringByPattern(*cpsUser.EmpGUIDsStr, "[^0-9]+")
  158. if len(*cpsUser.EmpGUIDsStr) > 0 {
  159. EmpGUIDsS := strings.Split(*cpsUser.EmpGUIDsStr, ",")
  160. for _, empGUIDS := range EmpGUIDsS {
  161. empGUID, err := strconv.Atoi(empGUIDS)
  162. if err != nil {
  163. panic(err)
  164. }
  165. person, err := asuModels.PersonSQL.First(asuModels.Person{EmpGUID: empGUID})
  166. if err == sql.ErrNoRows {
  167. revel.WARN.Printf("Cannot find person with EmpGUID == %v", empGUID)
  168. continue
  169. }
  170. if err != nil {
  171. panic(nil)
  172. }
  173. permissions.AllowedPeople = append(permissions.AllowedPeople, person)
  174. }
  175. }
  176. }
  177. permissions.AllowedPeople = permissions.AllowedPeople.Deduplicate()
  178. return permissions
  179. }
  180. func (p Permissions) GetShortForm() map[string]interface{} {
  181. permissions := map[string]interface{}{}
  182. permissions["isFullAccess"] = p.IsFullAccess
  183. permissions["isFixOk"] = p.IsFixOk
  184. if !p.IsFullAccess {
  185. var allowedUnits []map[string]interface{}
  186. for _, allowedUnit := range p.AllowedUnits {
  187. allowedUnits = append(allowedUnits, map[string]interface{}{
  188. "id": allowedUnit.Id,
  189. "code": allowedUnit.Code,
  190. "persNumber": allowedUnit.PersNumber,
  191. })
  192. }
  193. permissions["allowedUnits"] = allowedUnits
  194. permissions["allowedPeople"] = p.AllowedPeople.GetEmpGUIDs()
  195. }
  196. return permissions
  197. }