standalone.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. "strings"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/pkg/util/regutils"
  21. "yunion.io/x/sqlchemy"
  22. "yunion.io/x/onecloud/pkg/apis"
  23. "yunion.io/x/onecloud/pkg/httperrors"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. "yunion.io/x/onecloud/pkg/util/stringutils2"
  26. )
  27. type SStandaloneResourceBase struct {
  28. SStandaloneAnonResourceBase
  29. // 资源名称
  30. Name string `width:"128" charset:"utf8" nullable:"false" index:"true" list:"user" update:"user" create:"required" json:"name"`
  31. }
  32. type SStandaloneResourceBaseManager struct {
  33. SStandaloneAnonResourceBaseManager
  34. NameRequireAscii bool
  35. NameLength int
  36. }
  37. func NewStandaloneResourceBaseManager(
  38. dt interface{},
  39. tableName string,
  40. keyword string,
  41. keywordPlural string,
  42. ) SStandaloneResourceBaseManager {
  43. return SStandaloneResourceBaseManager{
  44. SStandaloneAnonResourceBaseManager: NewStandaloneAnonResourceBaseManager(dt, tableName, keyword, keywordPlural),
  45. }
  46. }
  47. func (manager *SStandaloneResourceBaseManager) HasName() bool {
  48. return true
  49. }
  50. func (manager *SStandaloneResourceBaseManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlchemy.SQuery {
  51. return q.Equals("name", name)
  52. }
  53. func (manager *SStandaloneResourceBaseManager) ValidateName(name string) error {
  54. if manager.NameRequireAscii && !regutils.MatchName(name) {
  55. return httperrors.NewInputParameterError("name starts with letter, and contains letter, number and ._@- only")
  56. }
  57. if manager.NameLength > 0 && len(name) > manager.NameLength {
  58. return httperrors.NewInputParameterError("name longer than %d", manager.NameLength)
  59. }
  60. return nil
  61. }
  62. func (manager *SStandaloneResourceBaseManager) FetchByName(ctx context.Context, userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
  63. return FetchByName(ctx, manager.GetIStandaloneModelManager(), userCred, idStr)
  64. }
  65. func (manager *SStandaloneResourceBaseManager) FetchByIdOrName(ctx context.Context, userCred mcclient.IIdentityProvider, idStr string) (IModel, error) {
  66. return FetchByIdOrName(ctx, manager.GetIStandaloneModelManager(), userCred, idStr)
  67. }
  68. func (manager *SStandaloneResourceBaseManager) ListItemFilter(
  69. ctx context.Context,
  70. q *sqlchemy.SQuery,
  71. userCred mcclient.TokenCredential,
  72. input apis.StandaloneResourceListInput,
  73. ) (*sqlchemy.SQuery, error) {
  74. q, err := manager.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneAnonResourceListInput)
  75. if err != nil {
  76. return q, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ListItemFilte")
  77. }
  78. if len(input.Names) > 0 {
  79. q = q.In("name", input.Names)
  80. }
  81. return q, nil
  82. }
  83. func (manager *SStandaloneResourceBaseManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
  84. var err error
  85. q, err = manager.SStandaloneAnonResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  86. if err != nil {
  87. return nil, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ListItemExportKeys")
  88. }
  89. if keys.Contains("user_tags") {
  90. userTagsQuery := Metadata.Query().Startswith("id", manager.keyword+"::").
  91. Startswith("key", USER_TAG_PREFIX).GroupBy("id")
  92. userTagsQuery.AppendField(sqlchemy.SubStr("resource_id", userTagsQuery.Field("id"), len(manager.keyword)+3, 0))
  93. userTagsQuery.AppendField(
  94. sqlchemy.GROUP_CONCAT("user_tags", sqlchemy.CONCAT("",
  95. sqlchemy.SubStr("", userTagsQuery.Field("key"), len(USER_TAG_PREFIX)+1, 0),
  96. sqlchemy.NewStringField(":"),
  97. userTagsQuery.Field("value"),
  98. )))
  99. subQ := userTagsQuery.SubQuery()
  100. q.LeftJoin(subQ, sqlchemy.Equals(q.Field("id"), subQ.Field("resource_id")))
  101. q.AppendField(subQ.Field("user_tags"))
  102. }
  103. return q, nil
  104. }
  105. func (manager *SStandaloneResourceBaseManager) OrderByExtraFields(
  106. ctx context.Context,
  107. q *sqlchemy.SQuery,
  108. userCred mcclient.TokenCredential,
  109. input apis.StandaloneResourceListInput,
  110. ) (*sqlchemy.SQuery, error) {
  111. q, err := manager.SStandaloneAnonResourceBaseManager.OrderByExtraFields(ctx, q, userCred, input.StandaloneAnonResourceListInput)
  112. if err != nil {
  113. return nil, errors.Wrap(err, "SResourceBaseManager.OrderByExtraFields")
  114. }
  115. return q, nil
  116. }
  117. func (model *SStandaloneResourceBase) GetName() string {
  118. return model.Name
  119. }
  120. func (model *SStandaloneResourceBase) SetName(name string) {
  121. model.Name = name
  122. }
  123. func (model *SStandaloneResourceBase) GetIStandaloneModel() IStandaloneModel {
  124. return model.GetVirtualObject().(IStandaloneModel)
  125. }
  126. func (model *SStandaloneResourceBase) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
  127. desc := model.SStandaloneAnonResourceBase.GetShortDesc(ctx)
  128. desc.Add(jsonutils.NewString(model.GetName()), "name")
  129. return desc
  130. }
  131. func (model *SStandaloneResourceBase) GetShortDescV2(ctx context.Context) *apis.StandaloneResourceShortDescDetail {
  132. desc := &apis.StandaloneResourceShortDescDetail{}
  133. desc.StandaloneAnonResourceShortDescDetail = *model.SStandaloneAnonResourceBase.GetShortDescV2(ctx)
  134. desc.Name = model.GetName()
  135. return desc
  136. }
  137. func (manager *SStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StandaloneResourceCreateInput) (apis.StandaloneResourceCreateInput, error) {
  138. var err error
  139. input.StandaloneAnonResourceCreateInput, err = manager.SStandaloneAnonResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneAnonResourceCreateInput)
  140. if err != nil {
  141. return input, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ValidateCreateData")
  142. }
  143. input.Name = strings.TrimSpace(input.Name)
  144. if strings.ContainsAny(input.Name, "\n\r\t") {
  145. return input, errors.Wrap(httperrors.ErrInputParameter, "name should not contains any \\n\\r\\t")
  146. }
  147. return input, nil
  148. }
  149. func (manager *SStandaloneResourceBaseManager) FetchCustomizeColumns(
  150. ctx context.Context,
  151. userCred mcclient.TokenCredential,
  152. query jsonutils.JSONObject,
  153. objs []interface{},
  154. fields stringutils2.SSortedStrings,
  155. isList bool,
  156. ) []apis.StandaloneResourceDetails {
  157. ret := make([]apis.StandaloneResourceDetails, len(objs))
  158. upperRet := manager.SStandaloneAnonResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  159. for i := range objs {
  160. ret[i] = apis.StandaloneResourceDetails{
  161. StandaloneAnonResourceDetails: upperRet[i],
  162. }
  163. }
  164. return ret
  165. }
  166. func (model *SStandaloneResourceBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.StandaloneResourceBaseUpdateInput) (apis.StandaloneResourceBaseUpdateInput, error) {
  167. var err error
  168. input.StandaloneAnonResourceBaseUpdateInput, err = model.SStandaloneAnonResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneAnonResourceBaseUpdateInput)
  169. if err != nil {
  170. return input, errors.Wrap(err, "SModelBase.ValidateUpdateData")
  171. }
  172. if len(input.Name) > 0 {
  173. input.Name = strings.TrimSpace(input.Name)
  174. if strings.ContainsAny(input.Name, "\n\r\t") {
  175. return input, errors.Wrap(httperrors.ErrInputParameter, "name should not contains any \\n\\r\\t")
  176. }
  177. err = alterNameValidator(ctx, model.GetIStandaloneModel(), input.Name)
  178. if err != nil {
  179. return input, errors.Wrap(err, "alterNameValidator")
  180. }
  181. }
  182. return input, nil
  183. }