id_mappings.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package models
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "time"
  20. "github.com/golang-plus/uuid"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/sqlchemy"
  23. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  24. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  25. )
  26. // +onecloud:swagger-gen-ignore
  27. type SIdmappingManager struct {
  28. db.SResourceBaseManager
  29. }
  30. var IdmappingManager *SIdmappingManager
  31. func init() {
  32. IdmappingManager = &SIdmappingManager{
  33. SResourceBaseManager: db.NewResourceBaseManager(
  34. SIdmapping{},
  35. "id_mapping",
  36. "id_mapping",
  37. "id_mappings",
  38. ),
  39. }
  40. IdmappingManager.SetVirtualObject(IdmappingManager)
  41. }
  42. /*
  43. +-------------+----------------------+------+-----+---------+-------+
  44. | Field | Type | Null | Key | Default | Extra |
  45. +-------------+----------------------+------+-----+---------+-------+
  46. | public_id | varchar(64) | NO | PRI | NULL | |
  47. | domain_id | varchar(64) | NO | MUL | NULL | |
  48. | local_id | varchar(64) | NO | | NULL | |
  49. | entity_type | enum('user','group') | NO | | NULL | |
  50. +-------------+----------------------+------+-----+---------+-------+
  51. */
  52. type SIdmapping struct {
  53. db.SResourceBase
  54. PublicId string `width:"64" charset:"ascii" nullable:"false" primary:"false"`
  55. IdpId string `name:"domain_id" width:"64" charset:"ascii" nullable:"false" primary:"true"`
  56. IdpEntityId string `name:"local_id" width:"128" charset:"utf8" nullable:"false" primary:"true"`
  57. EntityType string `width:"10" charset:"ascii" nullable:"false" primary:"true"`
  58. }
  59. func getIdmapKey(idpId string, entityId string, entityType string) string {
  60. return fmt.Sprintf("%s-%s-%s", entityType, idpId, entityId)
  61. }
  62. func filterByIdpAndEntityId(q *sqlchemy.SQuery, idpId string, entityId string, entityType string) *sqlchemy.SQuery {
  63. return q.Equals("domain_id", idpId).Equals("local_id", entityId).Equals("entity_type", entityType)
  64. }
  65. func (manager *SIdmappingManager) RegisterIdMap(ctx context.Context, idpId string, entityId string, entityType string) (string, error) {
  66. return manager.RegisterIdMapWithId(ctx, idpId, entityId, entityType, "")
  67. }
  68. func (manager *SIdmappingManager) RegisterIdMapWithId(ctx context.Context, idpId string, entityId string, entityType string, publicId string) (string, error) {
  69. key := getIdmapKey(idpId, entityId, entityType)
  70. lockman.LockRawObject(ctx, manager.Keyword(), key)
  71. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), key)
  72. q := filterByIdpAndEntityId(manager.RawQuery(), idpId, entityId, entityType)
  73. mapping := SIdmapping{}
  74. mapping.SetModelManager(manager, &mapping)
  75. err := q.First(&mapping)
  76. if err != nil && err != sql.ErrNoRows {
  77. return "", errors.Wrap(err, "Query")
  78. }
  79. if err == sql.ErrNoRows {
  80. if len(publicId) == 0 {
  81. u1, _ := uuid.NewV4()
  82. u2, _ := uuid.NewV4()
  83. publicId = u1.Format(uuid.StyleWithoutDash) + u2.Format(uuid.StyleWithoutDash)
  84. }
  85. mapping.PublicId = publicId
  86. mapping.IdpId = idpId
  87. mapping.IdpEntityId = entityId
  88. mapping.EntityType = entityType
  89. err = manager.TableSpec().Insert(ctx, &mapping)
  90. if err != nil {
  91. return "", errors.Wrap(err, "Insert")
  92. }
  93. } else {
  94. if mapping.Deleted {
  95. if len(publicId) == 0 {
  96. u1, _ := uuid.NewV4()
  97. u2, _ := uuid.NewV4()
  98. publicId = u1.Format(uuid.StyleWithoutDash) + u2.Format(uuid.StyleWithoutDash)
  99. }
  100. _, err = db.Update(&mapping, func() error {
  101. mapping.PublicId = publicId
  102. mapping.Deleted = false
  103. mapping.DeletedAt = time.Time{}
  104. return nil
  105. })
  106. if err != nil {
  107. return "", errors.Wrap(err, "undelete")
  108. }
  109. }
  110. }
  111. return mapping.PublicId, nil
  112. }
  113. func (manager *SIdmappingManager) FetchByIdpAndEntityId(ctx context.Context, idpId string, entityId string, entityType string) (string, error) {
  114. key := getIdmapKey(idpId, entityId, entityType)
  115. lockman.LockRawObject(ctx, manager.Keyword(), key)
  116. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), key)
  117. q := filterByIdpAndEntityId(manager.Query(), idpId, entityId, entityType)
  118. mapping := SIdmapping{}
  119. mapping.SetModelManager(manager, &mapping)
  120. err := q.First(&mapping)
  121. if err != nil {
  122. return "", err
  123. } else {
  124. return mapping.PublicId, nil
  125. }
  126. }
  127. func (manager *SIdmappingManager) FetchEntities(idStr string, entType string) ([]SIdmapping, error) {
  128. q := manager.Query().Equals("public_id", idStr).Equals("entity_type", entType)
  129. idMaps := make([]SIdmapping, 0)
  130. err := db.FetchModelObjects(manager, q, &idMaps)
  131. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  132. return nil, errors.Wrap(err, "FetchModelObjects")
  133. } else {
  134. return idMaps, nil
  135. }
  136. }
  137. func (manager *SIdmappingManager) FetchFirstEntity(idStr string, entType string) (*SIdmapping, error) {
  138. q := manager.Query().Equals("public_id", idStr).Equals("entity_type", entType)
  139. idMap := SIdmapping{}
  140. idMap.SetModelManager(manager, &idMap)
  141. err := q.First(&idMap)
  142. if err != nil {
  143. return nil, err
  144. }
  145. return &idMap, nil
  146. }
  147. func (manager *SIdmappingManager) deleteByIdpId(idpId string) error {
  148. return manager.deleteAny(idpId, "", "")
  149. }
  150. func (manager *SIdmappingManager) deleteAny(idpId string, entityType string, publicId string) error {
  151. q := manager.Query().Equals("domain_id", idpId)
  152. if len(entityType) > 0 {
  153. q = q.Equals("entity_type", entityType)
  154. }
  155. if len(publicId) > 0 {
  156. q = q.Equals("public_id", publicId)
  157. }
  158. idmappings := make([]SIdmapping, 0)
  159. err := db.FetchModelObjects(manager, q, &idmappings)
  160. if err != nil && err != sql.ErrNoRows {
  161. return errors.Wrap(err, "FetchModelObjects")
  162. }
  163. for i := range idmappings {
  164. _, err = db.Update(&idmappings[i], func() error {
  165. return idmappings[i].MarkDelete()
  166. })
  167. if err != nil {
  168. return errors.Wrap(err, "markdelete")
  169. }
  170. }
  171. return nil
  172. }
  173. func (manager *SIdmappingManager) FetchPublicIdsExcludesQuery(idpId string, entityType string, excludes []string) *sqlchemy.SQuery {
  174. q := manager.Query("public_id").Equals("domain_id", idpId)
  175. q = q.Equals("entity_type", entityType)
  176. if len(excludes) > 0 {
  177. q = q.NotIn("public_id", excludes)
  178. }
  179. return q
  180. }
  181. func (manager *SIdmappingManager) FetchPublicIdsExcludes(idpId string, entityType string, excludes []string) ([]string, error) {
  182. q := manager.FetchPublicIdsExcludesQuery(idpId, entityType, excludes)
  183. rows, err := q.Rows()
  184. if err != nil && err != sql.ErrNoRows {
  185. return nil, errors.Wrap(err, "q.Rows")
  186. }
  187. if rows == nil {
  188. return nil, nil
  189. }
  190. defer rows.Close()
  191. ret := make([]string, 0)
  192. for rows.Next() {
  193. var idStr string
  194. err = rows.Scan(&idStr)
  195. if err != nil {
  196. return nil, errors.Wrap(err, "rows.Scan")
  197. }
  198. ret = append(ret, idStr)
  199. }
  200. return ret, nil
  201. }
  202. func (manager *SIdmappingManager) deleteByPublicId(publicId string, entityType string) error {
  203. idmappings, err := manager.FetchEntities(publicId, entityType)
  204. if err != nil {
  205. if errors.Cause(err) == sql.ErrNoRows {
  206. return nil
  207. } else {
  208. return errors.Wrap(err, "manager.FetchEntities")
  209. }
  210. }
  211. for i := range idmappings {
  212. _, err = db.Update(&idmappings[i], func() error {
  213. return idmappings[i].MarkDelete()
  214. })
  215. if err != nil {
  216. return errors.Wrap(err, "markdelete")
  217. }
  218. }
  219. return nil
  220. }