scopedpolicies.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/util/rbacscope"
  20. "yunion.io/x/sqlchemy"
  21. api "yunion.io/x/onecloud/pkg/apis/yunionconf"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  23. "yunion.io/x/onecloud/pkg/httperrors"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. "yunion.io/x/onecloud/pkg/util/stringutils2"
  26. )
  27. // +onecloud:swagger-gen-model-singular=scopedpolicy
  28. // +onecloud:swagger-gen-model-plural=scopedpolicies
  29. type SScopedPolicyManager struct {
  30. db.SInfrasResourceBaseManager
  31. }
  32. var ScopedPolicyManager *SScopedPolicyManager
  33. func init() {
  34. ScopedPolicyManager = &SScopedPolicyManager{
  35. SInfrasResourceBaseManager: db.NewInfrasResourceBaseManager(
  36. SScopedPolicy{},
  37. "scopedpolicies_tbl",
  38. "scopedpolicy",
  39. "scopedpolicies",
  40. ),
  41. }
  42. ScopedPolicyManager.SetVirtualObject(ScopedPolicyManager)
  43. }
  44. type SScopedPolicy struct {
  45. db.SInfrasResourceBase
  46. // 策略类别
  47. Category string `width:"64" charset:"utf8" nullable:"false" list:"domain" create:"domain_required" index:"true"`
  48. // 策略内容
  49. Policies jsonutils.JSONObject `charset:"utf8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  50. }
  51. func (manager *SScopedPolicyManager) ValidateCreateData(
  52. ctx context.Context,
  53. userCred mcclient.TokenCredential,
  54. ownerId mcclient.IIdentityProvider,
  55. query jsonutils.JSONObject,
  56. input api.ScopedPolicyCreateInput,
  57. ) (api.ScopedPolicyCreateInput, error) {
  58. var err error
  59. if len(input.Category) == 0 {
  60. return input, errors.Wrap(httperrors.ErrInputParameter, "empty category")
  61. }
  62. input.InfrasResourceBaseCreateInput, err = manager.SInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.InfrasResourceBaseCreateInput)
  63. if err != nil {
  64. return input, errors.Wrap(err, "SInfrasResourceBaseManager.ValidateCreateData")
  65. }
  66. return input, nil
  67. }
  68. func (policy *SScopedPolicy) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ScopedPolicyUpdateInput) (api.ScopedPolicyUpdateInput, error) {
  69. var err error
  70. input.InfrasResourceBaseUpdateInput, err = policy.SInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.InfrasResourceBaseUpdateInput)
  71. if err != nil {
  72. return input, errors.Wrap(err, "SInfrasResourceBase.ValidateUpdateData")
  73. }
  74. return input, nil
  75. }
  76. func (policy *SScopedPolicy) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  77. cnt, err := policy.getReferenceCount()
  78. if err != nil {
  79. return httperrors.NewInternalServerError("getReferenceCount fail %s", err)
  80. }
  81. if cnt > 0 {
  82. return httperrors.NewNotEmptyError("policy is referenced")
  83. }
  84. return policy.SInfrasResourceBase.ValidateDeleteCondition(ctx, nil)
  85. }
  86. func (policy *SScopedPolicy) getReferenceCount() (int, error) {
  87. return ScopedPolicyBindingManager.getReferenceCount(policy.Id)
  88. }
  89. // 范围策略列表
  90. func (manager *SScopedPolicyManager) ListItemFilter(
  91. ctx context.Context,
  92. q *sqlchemy.SQuery,
  93. userCred mcclient.TokenCredential,
  94. query api.ScopedPolicyListInput,
  95. ) (*sqlchemy.SQuery, error) {
  96. var err error
  97. q, err = manager.SInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.InfrasResourceBaseListInput)
  98. if err != nil {
  99. return nil, errors.Wrap(err, "SInfrasResourceBaseManager.ListItemFilter")
  100. }
  101. if len(query.Category) > 0 {
  102. q = q.Filter(sqlchemy.ContainsAny(q.Field("category"), query.Category))
  103. }
  104. return q, nil
  105. }
  106. func (manager *SScopedPolicyManager) OrderByExtraFields(
  107. ctx context.Context,
  108. q *sqlchemy.SQuery,
  109. userCred mcclient.TokenCredential,
  110. query api.ScopedPolicyListInput,
  111. ) (*sqlchemy.SQuery, error) {
  112. var err error
  113. q, err = manager.SInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.InfrasResourceBaseListInput)
  114. if err != nil {
  115. return nil, errors.Wrap(err, "SInfrasResourceBaseManager.OrderByExtraFields")
  116. }
  117. return q, nil
  118. }
  119. func (manager *SScopedPolicyManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  120. var err error
  121. q, err = manager.SInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
  122. if err == nil {
  123. return q, nil
  124. }
  125. return q, httperrors.ErrNotFound
  126. }
  127. func (manager *SScopedPolicyManager) FetchCustomizeColumns(
  128. ctx context.Context,
  129. userCred mcclient.TokenCredential,
  130. query jsonutils.JSONObject,
  131. objs []interface{},
  132. fields stringutils2.SSortedStrings,
  133. isList bool,
  134. ) []api.ScopedPolicyDetails {
  135. rows := make([]api.ScopedPolicyDetails, len(objs))
  136. stdRows := manager.SInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  137. for i := range rows {
  138. rows[i] = api.ScopedPolicyDetails{
  139. InfrasResourceBaseDetails: stdRows[i],
  140. }
  141. rows[i].RefCount, _ = objs[i].(*SScopedPolicy).getReferenceCount()
  142. }
  143. return rows
  144. }
  145. func (manager *SScopedPolicyManager) ListItemExportKeys(ctx context.Context,
  146. q *sqlchemy.SQuery,
  147. userCred mcclient.TokenCredential,
  148. keys stringutils2.SSortedStrings,
  149. ) (*sqlchemy.SQuery, error) {
  150. var err error
  151. q, err = manager.SInfrasResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  152. if err != nil {
  153. return nil, errors.Wrap(err, "SInfrasResourceBaseManager.ListItemExportKeys")
  154. }
  155. return q, nil
  156. }
  157. func (policy *SScopedPolicy) PerformBind(
  158. ctx context.Context,
  159. userCred mcclient.TokenCredential,
  160. query jsonutils.JSONObject,
  161. input api.ScopedPolicyBindInput,
  162. ) (jsonutils.JSONObject, error) {
  163. switch input.Scope {
  164. case rbacscope.ScopeSystem:
  165. err := ScopedPolicyBindingManager.bind(ctx, policy.Category, policy.Id, "", "")
  166. if err != nil {
  167. return nil, errors.Wrap(err, "bind system")
  168. }
  169. case rbacscope.ScopeDomain:
  170. for i := range input.TargetIds {
  171. if input.TargetIds[i] == api.ANY_DOMAIN_ID {
  172. err := ScopedPolicyBindingManager.bind(ctx, policy.Category, policy.Id, api.ANY_DOMAIN_ID, "")
  173. if err != nil {
  174. return nil, errors.Wrap(err, "bind all domain")
  175. }
  176. } else {
  177. domainObj, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, input.TargetIds[i])
  178. if err != nil {
  179. return nil, errors.Wrap(err, "FetchDomainByIdOrName")
  180. }
  181. err = ScopedPolicyBindingManager.bind(ctx, policy.Category, policy.Id, domainObj.GetId(), "")
  182. if err != nil {
  183. return nil, errors.Wrapf(err, "bind domain %s", domainObj.GetName())
  184. }
  185. }
  186. }
  187. case rbacscope.ScopeProject:
  188. for i := range input.TargetIds {
  189. if input.TargetIds[i] == api.ANY_PROJECT_ID {
  190. err := ScopedPolicyBindingManager.bind(ctx, policy.Category, policy.Id, api.ANY_DOMAIN_ID, api.ANY_PROJECT_ID)
  191. if err != nil {
  192. return nil, errors.Wrap(err, "bind all project")
  193. }
  194. } else {
  195. tenantObj, err := db.TenantCacheManager.FetchTenantById(ctx, input.TargetIds[i])
  196. if err != nil {
  197. return nil, errors.Wrap(err, "FetchTenantByIdOrName")
  198. }
  199. err = ScopedPolicyBindingManager.bind(ctx, policy.Category, policy.Id, tenantObj.DomainId, tenantObj.Id)
  200. if err != nil {
  201. return nil, errors.Wrapf(err, "bind project %s", tenantObj.GetName())
  202. }
  203. }
  204. }
  205. }
  206. return nil, nil
  207. }