tenantcache.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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 db
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "runtime/debug"
  20. "strings"
  21. "time"
  22. "yunion.io/x/jsonutils"
  23. "yunion.io/x/log"
  24. "yunion.io/x/pkg/errors"
  25. "yunion.io/x/pkg/util/httputils"
  26. "yunion.io/x/sqlchemy"
  27. identityapi "yunion.io/x/onecloud/pkg/apis/identity"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  30. "yunion.io/x/onecloud/pkg/httperrors"
  31. "yunion.io/x/onecloud/pkg/mcclient"
  32. "yunion.io/x/onecloud/pkg/mcclient/auth"
  33. modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
  34. "yunion.io/x/onecloud/pkg/util/stringutils2"
  35. "yunion.io/x/onecloud/pkg/util/tagutils"
  36. )
  37. var (
  38. DefaultProjectFetcher func(ctx context.Context, id string, domainId string) (*STenant, error)
  39. DefaultDomainFetcher func(ctx context.Context, id string) (*STenant, error)
  40. DefaultProjectsFetcher func(ctx context.Context, idList []string, isDomain bool) map[string]STenant
  41. DefaultDomainQuery func(fields ...string) *sqlchemy.SQuery
  42. DefaultProjectQuery func(fields ...string) *sqlchemy.SQuery
  43. )
  44. type STenantCacheManager struct {
  45. SKeystoneCacheObjectManager
  46. }
  47. type STenant struct {
  48. SKeystoneCacheObject
  49. }
  50. func (t *STenant) GetTags() tagutils.TTagSet {
  51. objType := "project"
  52. if t.Domain == identityapi.KeystoneDomainRoot && t.DomainId == identityapi.KeystoneDomainRoot {
  53. objType = "domain"
  54. }
  55. tags, _ := Metadata.rawGetAll(objType, t.Id, nil, "")
  56. return tagutils.Map2Tagset(tags)
  57. }
  58. func NewTenant(idStr string, name string, domainId string, domainName string) STenant {
  59. return STenant{SKeystoneCacheObject: NewKeystoneCacheObject(idStr, name, domainId, domainName)}
  60. }
  61. func NewDomain(idStr, name string) STenant {
  62. return NewTenant(idStr, name, identityapi.KeystoneDomainRoot, identityapi.KeystoneDomainRoot)
  63. }
  64. func (tenant *STenant) GetModelManager() IModelManager {
  65. return TenantCacheManager
  66. }
  67. var TenantCacheManager *STenantCacheManager
  68. func init() {
  69. TenantCacheManager = &STenantCacheManager{
  70. SKeystoneCacheObjectManager: NewKeystoneCacheObjectManager(
  71. STenant{},
  72. "tenant_cache_tbl",
  73. "tenant_cache",
  74. "tenant_caches",
  75. )}
  76. // log.Debugf("Initialize tenant cache manager %s %s", TenantCacheManager.KeywordPlural(), TenantCacheManager)
  77. TenantCacheManager.SetVirtualObject(TenantCacheManager)
  78. DefaultProjectFetcher = TenantCacheManager.FetchTenantByIdOrNameInDomain
  79. DefaultDomainFetcher = TenantCacheManager.FetchDomainByIdOrName
  80. DefaultProjectsFetcher = fetchProjects
  81. DefaultDomainQuery = TenantCacheManager.GetDomainQuery
  82. DefaultProjectQuery = TenantCacheManager.GetTenantQuery
  83. }
  84. func RegistUserCredCacheUpdater() {
  85. auth.RegisterAuthHook(onAuthCompleteUpdateCache)
  86. }
  87. func onAuthCompleteUpdateCache(ctx context.Context, userCred mcclient.TokenCredential) {
  88. TenantCacheManager.updateTenantCache(ctx, userCred)
  89. UserCacheManager.updateUserCache(ctx, userCred)
  90. }
  91. func (manager *STenantCacheManager) InitializeData() error {
  92. q := manager.Query().IsNullOrEmpty("domain_id")
  93. tenants := make([]STenant, 0)
  94. err := FetchModelObjects(manager, q, &tenants)
  95. if err != nil && err != sql.ErrNoRows {
  96. return errors.Wrap(err, "query")
  97. }
  98. for i := range tenants {
  99. _, err := Update(&tenants[i], func() error {
  100. tenants[i].DomainId = identityapi.DEFAULT_DOMAIN_ID
  101. tenants[i].Domain = identityapi.DEFAULT_DOMAIN_NAME
  102. return nil
  103. })
  104. if err != nil {
  105. return errors.Wrap(err, "update")
  106. }
  107. }
  108. return nil
  109. }
  110. func (manager *STenantCacheManager) updateTenantCache(ctx context.Context, userCred mcclient.TokenCredential) {
  111. item := SCachedTenant{
  112. Id: userCred.GetProjectId(),
  113. Name: userCred.GetProjectName(),
  114. DomainId: userCred.GetProjectDomainId(),
  115. ProjectDomain: userCred.GetProjectDomain(),
  116. }
  117. manager.Save(ctx, item, false)
  118. }
  119. func (manager *STenantCacheManager) GetTenantQuery(fields ...string) *sqlchemy.SQuery {
  120. return manager.Query(fields...).NotEquals("domain_id", identityapi.KeystoneDomainRoot)
  121. }
  122. func (manager *STenantCacheManager) GetDomainQuery(fields ...string) *sqlchemy.SQuery {
  123. return manager.Query(fields...).Equals("domain_id", identityapi.KeystoneDomainRoot)
  124. }
  125. func (manager *STenantCacheManager) fetchTenant(ctx context.Context, idStr string, domainId string, isDomain bool, noExpireCheck bool, filter func(q *sqlchemy.SQuery) *sqlchemy.SQuery) (*STenant, error) {
  126. var q *sqlchemy.SQuery
  127. if isDomain {
  128. q = manager.GetDomainQuery()
  129. } else {
  130. q = manager.GetTenantQuery()
  131. if len(domainId) > 0 {
  132. q = q.Equals("domain_id", domainId)
  133. }
  134. }
  135. q = filter(q)
  136. caches := []STenant{}
  137. err := FetchModelObjects(manager, q, &caches)
  138. if err != nil {
  139. return nil, errors.Wrap(err, "FetchModelObjects")
  140. }
  141. normal := []STenant{}
  142. for _, cache := range caches {
  143. if noExpireCheck || !cache.IsExpired() {
  144. normal = append(normal, cache)
  145. }
  146. }
  147. if len(normal) > 1 {
  148. return nil, errors.Wrapf(httperrors.ErrDuplicateName, "duplicate tenant/domain name (%d)", len(normal))
  149. }
  150. if len(normal) == 1 {
  151. return &normal[0], nil
  152. }
  153. if isDomain {
  154. return manager.fetchDomainFromKeystone(ctx, idStr)
  155. } else {
  156. return manager.fetchTenantFromKeystone(ctx, idStr, domainId)
  157. }
  158. }
  159. func (t *STenant) IsExpired() bool {
  160. if t.LastCheck.IsZero() {
  161. return true
  162. }
  163. now := time.Now().UTC()
  164. if t.LastCheck.Add(consts.GetTenantCacheExpireSeconds()).Before(now) {
  165. return true
  166. }
  167. return false
  168. }
  169. func (manager *STenantCacheManager) FetchTenantByIdOrNameInDomain(ctx context.Context, idStr string, domainId string) (*STenant, error) {
  170. if !stringutils2.IsUtf8(idStr) {
  171. t, err := manager.FetchTenantById(ctx, idStr)
  172. if t != nil {
  173. return t, nil
  174. } else if err != nil && errors.Cause(err) != sql.ErrNoRows {
  175. return nil, errors.Wrap(err, "FetchTenantById")
  176. }
  177. }
  178. return manager.fetchTenant(ctx, idStr, domainId, false, false, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  179. if stringutils2.IsUtf8(idStr) {
  180. return q.Equals("name", idStr)
  181. } else {
  182. return q.Filter(sqlchemy.OR(
  183. sqlchemy.Equals(q.Field("id"), idStr),
  184. sqlchemy.Equals(q.Field("name"), idStr),
  185. ))
  186. }
  187. })
  188. }
  189. func (manager *STenantCacheManager) FetchTenantById(ctx context.Context, idStr string) (*STenant, error) {
  190. return manager.fetchTenantById(ctx, idStr, false)
  191. }
  192. func (manager *STenantCacheManager) FetchTenantByIdWithoutExpireCheck(ctx context.Context, idStr string) (*STenant, error) {
  193. // noExpireCheck should be true
  194. return manager.fetchTenantById(ctx, idStr, true)
  195. }
  196. func (manager *STenantCacheManager) fetchTenantById(ctx context.Context, idStr string, noExpireCheck bool) (*STenant, error) {
  197. return manager.fetchTenant(ctx, idStr, "", false, noExpireCheck, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  198. return q.Filter(sqlchemy.Equals(q.Field("id"), idStr))
  199. })
  200. }
  201. func (manager *STenantCacheManager) FetchTenantByNameInDomain(ctx context.Context, idStr string, domainId string) (*STenant, error) {
  202. return manager.fetchTenant(ctx, idStr, domainId, false, false, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  203. return q.Filter(sqlchemy.Equals(q.Field("name"), idStr))
  204. })
  205. }
  206. func (manager *STenantCacheManager) fetchTenantFromKeystone(ctx context.Context, idStr string, domainId string) (*STenant, error) {
  207. if len(idStr) == 0 {
  208. log.Debugf("fetch empty tenant!!!!\n%s", debug.Stack())
  209. return nil, fmt.Errorf("Empty idStr")
  210. }
  211. // It is to query all domain's project.
  212. query := jsonutils.NewDict()
  213. query.Set("scope", jsonutils.NewString("system"))
  214. if len(domainId) > 0 {
  215. query.Set("domain_id", jsonutils.NewString(domainId))
  216. }
  217. query.Set("pending_delete", jsonutils.NewString("all"))
  218. s := auth.GetAdminSession(ctx, consts.GetRegion())
  219. tenant, err := modules.Projects.GetById(s, idStr, query)
  220. if err != nil {
  221. if je, ok := err.(*httputils.JSONClientError); ok && je.Code == 404 {
  222. return nil, sql.ErrNoRows
  223. }
  224. log.Errorf("fetch project %s fail %s", idStr, err)
  225. return nil, errors.Wrap(err, "modules.Projects.Get")
  226. }
  227. var item SCachedTenant
  228. err = tenant.Unmarshal(&item)
  229. if err != nil {
  230. return nil, errors.Wrapf(err, "Unmarshal %s", tenant)
  231. }
  232. return manager.Save(ctx, item, true)
  233. }
  234. func (manager *STenantCacheManager) FetchDomainByIdOrName(ctx context.Context, idStr string) (*STenant, error) {
  235. return manager.fetchTenant(ctx, idStr, "", true, false, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  236. if stringutils2.IsUtf8(idStr) {
  237. return q.Equals("name", idStr)
  238. } else {
  239. return q.Filter(sqlchemy.OR(
  240. sqlchemy.Equals(q.Field("id"), idStr),
  241. sqlchemy.Equals(q.Field("name"), idStr),
  242. ))
  243. }
  244. })
  245. }
  246. func (manager *STenantCacheManager) FetchDomainById(ctx context.Context, idStr string) (*STenant, error) {
  247. return manager.fetchDomainById(ctx, idStr, false)
  248. }
  249. func (manager *STenantCacheManager) FetchDomainByIdWithoutExpireCheck(ctx context.Context, idStr string) (*STenant, error) {
  250. return manager.fetchDomainById(ctx, idStr, true)
  251. }
  252. func (manager *STenantCacheManager) fetchDomainById(ctx context.Context, idStr string, noExpireCheck bool) (*STenant, error) {
  253. return manager.fetchTenant(ctx, idStr, "", true, noExpireCheck, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  254. return q.Filter(sqlchemy.Equals(q.Field("id"), idStr))
  255. })
  256. }
  257. func (manager *STenantCacheManager) FetchDomainByName(ctx context.Context, idStr string) (*STenant, error) {
  258. return manager.fetchTenant(ctx, idStr, "", true, false, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  259. return q.Filter(sqlchemy.Equals(q.Field("name"), idStr))
  260. })
  261. }
  262. func (manager *STenantCacheManager) fetchDomainFromKeystone(ctx context.Context, idStr string) (*STenant, error) {
  263. if len(idStr) == 0 {
  264. log.Debugf("fetch empty domain!!!!\n%s", debug.Stack())
  265. return nil, fmt.Errorf("Empty idStr")
  266. }
  267. s := auth.GetAdminSession(ctx, consts.GetRegion())
  268. tenant, err := modules.Domains.GetById(s, idStr, nil)
  269. if err != nil {
  270. if je, ok := err.(*httputils.JSONClientError); ok && je.Code == 404 {
  271. return nil, sql.ErrNoRows
  272. }
  273. log.Errorf("fetch project %s fail %s", idStr, err)
  274. return nil, errors.Wrap(err, "modules.Projects.Get")
  275. }
  276. var item SCachedTenant
  277. err = tenant.Unmarshal(&item)
  278. if err != nil {
  279. return nil, errors.Wrapf(err, "Unmarshal %s", tenant)
  280. }
  281. item.DomainId = identityapi.KeystoneDomainRoot
  282. item.ProjectDomain = identityapi.KeystoneDomainRoot
  283. return manager.Save(ctx, item, true)
  284. }
  285. func (manager *STenantCacheManager) Delete(ctx context.Context, idStr string) error {
  286. lockman.LockRawObject(ctx, manager.KeywordPlural(), idStr)
  287. defer lockman.ReleaseRawObject(ctx, manager.KeywordPlural(), idStr)
  288. objo, err := manager.FetchById(idStr)
  289. if err != nil && err != sql.ErrNoRows {
  290. log.Errorf("FetchTenantbyId fail %s", err)
  291. return err
  292. }
  293. if err == sql.ErrNoRows {
  294. return nil
  295. }
  296. return objo.Delete(ctx, nil)
  297. }
  298. func (manager *STenantCacheManager) Save(ctx context.Context, item SCachedTenant, saveMeta bool) (*STenant, error) {
  299. lockman.LockRawObject(ctx, manager.KeywordPlural(), item.Id)
  300. defer lockman.ReleaseRawObject(ctx, manager.KeywordPlural(), item.Id)
  301. objo, err := manager.FetchById(item.Id)
  302. if err != nil && err != sql.ErrNoRows {
  303. log.Errorf("FetchTenantbyId fail %s", err)
  304. return nil, errors.Wrapf(err, "TenantCache FetchById %s", item.Id)
  305. }
  306. // clean cache metadata
  307. if item.PendingDeleted && saveMeta {
  308. for k := range item.Metadata {
  309. if strings.HasPrefix(k, USER_TAG_PREFIX) {
  310. item.Metadata[k] = "none"
  311. }
  312. }
  313. }
  314. now := time.Now().UTC()
  315. if err == nil {
  316. obj := objo.(*STenant)
  317. if obj.Id == item.Id && obj.Name == item.Name && obj.Domain == item.ProjectDomain && obj.DomainId == item.DomainId {
  318. Update(obj, func() error {
  319. obj.LastCheck = now
  320. obj.PendingDeleted = item.PendingDeleted
  321. if obj.PendingDeleted {
  322. obj.PendingDeletedAt = item.PendingDeletedAt
  323. }
  324. return nil
  325. })
  326. if saveMeta {
  327. Metadata.rawSetValues(ctx, item.objType(), item.Id, item.Metadata, true, "")
  328. }
  329. return obj, nil
  330. }
  331. _, err = Update(obj, func() error {
  332. obj.Id = item.Id
  333. obj.Name = item.Name
  334. obj.Domain = item.ProjectDomain
  335. obj.DomainId = item.DomainId
  336. obj.LastCheck = now
  337. obj.PendingDeleted = item.PendingDeleted
  338. if obj.PendingDeleted {
  339. obj.PendingDeletedAt = item.PendingDeletedAt
  340. }
  341. return nil
  342. })
  343. if err != nil {
  344. return nil, err
  345. } else {
  346. if saveMeta {
  347. Metadata.rawSetValues(ctx, item.objType(), item.Id, item.Metadata, true, "")
  348. }
  349. return obj, nil
  350. }
  351. } else {
  352. objm, err := NewModelObject(manager)
  353. obj := objm.(*STenant)
  354. obj.Id = item.Id
  355. obj.Name = item.Name
  356. obj.Domain = item.ProjectDomain
  357. obj.DomainId = item.DomainId
  358. obj.LastCheck = now
  359. obj.PendingDeleted = item.PendingDeleted
  360. if obj.PendingDeleted {
  361. obj.PendingDeletedAt = item.PendingDeletedAt
  362. }
  363. err = manager.TableSpec().InsertOrUpdate(ctx, obj)
  364. if err != nil {
  365. return nil, errors.Wrap(err, "InsertOrUpdate")
  366. } else {
  367. if saveMeta {
  368. Metadata.rawSetValues(ctx, item.objType(), item.Id, item.Metadata, true, "")
  369. }
  370. return obj, nil
  371. }
  372. }
  373. }
  374. /*func (manager *STenantCacheManager) GenerateProjectUserCred(ctx context.Context, projectName string) (mcclient.TokenCredential, error) {
  375. project, err := manager.FetchTenantByIdOrName(ctx, projectName)
  376. if err != nil {
  377. return nil, err
  378. }
  379. return &mcclient.SSimpleToken{
  380. Project: project.Name,
  381. ProjectId: project.Id,
  382. }, nil
  383. }*/
  384. /*func (tenant *STenant) GetDomain() string {
  385. if len(tenant.Domain) == 0 {
  386. return identityapi.DEFAULT_DOMAIN_NAME
  387. }
  388. return tenant.Domain
  389. }
  390. func (tenant *STenant) GetDomainId() string {
  391. if len(tenant.DomainId) == 0 {
  392. return identityapi.DEFAULT_DOMAIN_ID
  393. }
  394. return tenant.DomainId
  395. }*/
  396. func (manager *STenantCacheManager) findFirstProjectOfDomain(domainId string) (*STenant, error) {
  397. q := manager.Query().Equals("domain_id", domainId).Asc("created_at")
  398. tenant := STenant{}
  399. tenant.SetModelManager(manager, &tenant)
  400. err := q.First(&tenant)
  401. if err != nil {
  402. return nil, err
  403. }
  404. return &tenant, nil
  405. }
  406. func (manager *STenantCacheManager) fetchDomainTenantsFromKeystone(ctx context.Context, domainId string) error {
  407. if len(domainId) == 0 {
  408. log.Debugf("fetch empty domain!!!!")
  409. debug.PrintStack()
  410. return fmt.Errorf("Empty domainId")
  411. }
  412. s := auth.GetAdminSession(ctx, consts.GetRegion())
  413. params := jsonutils.NewDict()
  414. params.Add(jsonutils.NewString(domainId), "domain_id")
  415. params.Add(jsonutils.JSONTrue, "details")
  416. params.Add(jsonutils.NewString("all"), "pending_delete")
  417. tenants, err := modules.Projects.List(s, params)
  418. if err != nil {
  419. return errors.Wrap(err, "Projects.List")
  420. }
  421. for _, tenant := range tenants.Data {
  422. var item SCachedTenant
  423. err := tenant.Unmarshal(&item)
  424. if err != nil {
  425. return errors.Wrapf(err, "Unmarshal %s", tenant)
  426. }
  427. _, err = manager.Save(ctx, item, true)
  428. if err != nil {
  429. return errors.Wrap(err, "save")
  430. }
  431. }
  432. return nil
  433. }
  434. func (manager *STenantCacheManager) FindFirstProjectOfDomain(ctx context.Context, domainId string) (*STenant, error) {
  435. tenant, err := manager.findFirstProjectOfDomain(domainId)
  436. if err != nil {
  437. if err == sql.ErrNoRows {
  438. err = manager.fetchDomainTenantsFromKeystone(ctx, domainId)
  439. if err != nil {
  440. return nil, errors.Wrap(err, "fetchDomainTenantsFromKeystone")
  441. }
  442. return manager.findFirstProjectOfDomain(domainId)
  443. }
  444. return nil, errors.Wrap(err, "findFirstProjectOfDomain.queryFirst")
  445. }
  446. return tenant, nil
  447. }
  448. func (tenant *STenant) GetProjectId() string {
  449. if tenant.IsDomain() {
  450. return ""
  451. } else {
  452. return tenant.Id
  453. }
  454. }
  455. func (tenant *STenant) GetTenantId() string {
  456. return tenant.GetProjectId()
  457. }
  458. func (tenant *STenant) GetProjectDomainId() string {
  459. if tenant.IsDomain() {
  460. return tenant.Id
  461. } else {
  462. return tenant.DomainId
  463. }
  464. }
  465. func (tenant *STenant) GetTenantName() string {
  466. return tenant.GetProjectName()
  467. }
  468. func (tenant *STenant) GetProjectName() string {
  469. if tenant.IsDomain() {
  470. return ""
  471. } else {
  472. return tenant.Name
  473. }
  474. }
  475. func (tenant *STenant) GetProjectDomain() string {
  476. if tenant.IsDomain() {
  477. return tenant.Name
  478. } else {
  479. return tenant.Domain
  480. }
  481. }
  482. func (tenant *STenant) GetUserId() string {
  483. return ""
  484. }
  485. func (tenant *STenant) GetUserName() string {
  486. return ""
  487. }
  488. func (tenant *STenant) GetDomainId() string {
  489. return ""
  490. }
  491. func (tenant *STenant) GetDomainName() string {
  492. return ""
  493. }
  494. func (tenant *STenant) IsDomain() bool {
  495. if tenant.DomainId == identityapi.KeystoneDomainRoot {
  496. return true
  497. } else {
  498. return false
  499. }
  500. }
  501. func (tenant *STenant) objType() string {
  502. if tenant.IsDomain() {
  503. return "domain"
  504. } else {
  505. return "project"
  506. }
  507. }
  508. func (tenant *STenant) GetAllClassMetadata() (map[string]string, error) {
  509. meta, err := Metadata.rawGetAll(tenant.objType(), tenant.GetId(), nil, CLASS_TAG_PREFIX)
  510. if err != nil {
  511. return nil, errors.Wrap(err, "rawGetAll")
  512. }
  513. ret := make(map[string]string)
  514. for k, v := range meta {
  515. if strings.HasPrefix(k, SYSTEM_ADMIN_PREFIX) {
  516. continue
  517. }
  518. ret[k[len(CLASS_TAG_PREFIX):]] = v
  519. }
  520. return ret, nil
  521. }
  522. func (manager *STenantCacheManager) ConvertIds(ids []string, isDomain bool) ([]string, error) {
  523. var q *sqlchemy.SQuery
  524. if isDomain {
  525. q = manager.GetDomainQuery("id")
  526. } else {
  527. q = manager.GetTenantQuery("id")
  528. }
  529. q = q.Filter(sqlchemy.OR(
  530. sqlchemy.In(q.Field("id"), stringutils2.RemoveUtf8Strings(ids)),
  531. sqlchemy.In(q.Field("name"), ids),
  532. ))
  533. q = q.Distinct()
  534. results := []struct {
  535. Id string
  536. }{}
  537. err := q.All(&results)
  538. if err != nil {
  539. return nil, errors.Wrap(err, "query")
  540. }
  541. ret := make([]string, len(results))
  542. for i := range results {
  543. ret[i] = results[i].Id
  544. }
  545. return ret, nil
  546. }