feat(notify): Compatibility and repair

This commit is contained in:
Rain
2020-03-11 17:03:57 +08:00
parent 0c995ce925
commit 0cb0ba6f1b
14 changed files with 214 additions and 86 deletions

View File

@@ -29,11 +29,11 @@ func init() {
* 操作用户的通信地址(如果用户的通信地址不存在则进行添加;如果已存在则进行修改;如果设置空则进行删除。)
*/
type ContactsUpdateOptions struct {
UID string `help:"The user you wanna add contact to (Keystone User ID)"`
CONTACTTYPE string `help:"The contact type email|mobile" choices:"email|mobile|dingtalk"`
CONTACT string `help:"The contacts details mobile number or email address or dingtalk's userid, if set it the empty str means delete"`
Status string `help:"Enabled or disabled contact status" choices:"enable|disable"`
Pull string `help:"pull some subcontacts(e.g., dingtalk, feishu, etc) related to mobile"`
UID string `help:"The user you wanna add contact to (Keystone User ID)"`
CONTACTTYPE string `help:"The contact type email|mobile" choices:"email|mobile|dingtalk"`
CONTACT string `help:"The contacts details mobile number or email address or dingtalk's userid, if set it the empty str means delete"`
Status string `help:"Enabled or disabled contact status" choices:"enable|disable"`
Pull []string `help:"pull some subcontacts(e.g., dingtalk, feishu, etc) related to mobile"`
}
R(&ContactsUpdateOptions{}, "contact-update", "Create, delete or update contact for user", func(s *mcclient.ClientSession, args *ContactsUpdateOptions) error {
arr := jsonutils.NewArray()
@@ -53,7 +53,13 @@ func init() {
params := jsonutils.NewDict()
params.Add(arr, "contacts")
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", args.Pull, params)
pulls := jsonutils.NewArray()
for _, pull := range args.Pull {
pulls.Add(jsonutils.NewString(pull))
}
params.Add(pulls, "pull")
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
if err != nil {
return err
}
@@ -69,7 +75,8 @@ func init() {
R(&ContactsPullOptions{}, "contact-pull", "Pull contact", func(s *mcclient.ClientSession, args *ContactsPullOptions) error {
params := jsonutils.NewDict()
params.Set("contacts", jsonutils.NewArray())
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", args.CONTACTTYPE, params)
params.Set("pull", jsonutils.NewArray(jsonutils.NewString(args.CONTACTTYPE)))
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
if err != nil {
return err
}
@@ -89,7 +96,7 @@ func init() {
arr.Add(tmpObj)
params := jsonutils.NewDict()
params.Add(arr, "contacts")
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", "", params)
contact, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "update-contact", params)
if err != nil {
return err
}
@@ -180,7 +187,7 @@ func init() {
tmpDict := jsonutils.NewDict()
tmpDict.Add(jsonutils.NewString(args.CONTACT_TYPE), "contact_type")
tmpDict.Add(jsonutils.NewString(args.CONTACT), "contact")
_, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "verify", "", tmpDict)
_, err := modules.Contacts.CustomizedPerformAction(s, args.UID, "verify", tmpDict)
if err != nil {
return err
}

View File

@@ -41,7 +41,7 @@ func init() {
NotificationCreateOptions
}
R(&NotificationCreateSingleOptions{}, "notify", "Send a notification to someones", func(s *mcclient.ClientSession,
R(&NotificationCreateSingleOptions{}, "notify", "Send a notification to someone", func(s *mcclient.ClientSession,
args *NotificationCreateSingleOptions) error {
msg := notify.SNotifyMessage{}

View File

@@ -19,7 +19,7 @@ import "yunion.io/x/onecloud/pkg/apis"
type ContactDetails struct {
apis.ResourceBaseDetails
Id string `json:"id"`
UID string `json:"uid"`
Name string `json:"name"`
Details string `json:"details"`
}

View File

@@ -19,6 +19,7 @@ import (
"database/sql"
"fmt"
"runtime/debug"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -155,6 +156,7 @@ func (manager *SUserCacheManager) Save(ctx context.Context, idStr string, name s
obj.Name = name
obj.Domain = domain
obj.DomainId = domainId
obj.LastCheck = time.Now().UTC()
return nil
})
if err != nil {
@@ -169,7 +171,8 @@ func (manager *SUserCacheManager) Save(ctx context.Context, idStr string, name s
obj.Name = name
obj.Domain = domain
obj.DomainId = domainId
err = manager.TableSpec().Insert(obj)
obj.LastCheck = time.Now().UTC()
err = manager.TableSpec().InsertOrUpdate(obj)
if err != nil {
return nil, err
} else {

View File

@@ -40,22 +40,17 @@ func (this *ContactsManager) PerformActionWithArrayParams(s *mcclient.ClientSess
}
func (this *ContactsManager) DoBatchDeleteContacts(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
path := "/contacts/delete-contact"
path := "/contacts/delete-contact?uname=true"
return modulebase.Post(this.ResourceManager, s, path, params, this.Keyword)
}
func (this *ContactsManager) CustomizedPerformAction(session *mcclient.ClientSession, id, action, pull string,
params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (this *ContactsManager) CustomizedPerformAction(session *mcclient.ClientSession, id, action string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
body := jsonutils.NewDict()
if params != nil {
body.Add(params, this.Keyword)
}
path := fmt.Sprintf("/%s/%s/%s?uname=true", this.ContextPath(nil), url.PathEscape(id), url.PathEscape(action))
if len(pull) > 0 {
path += fmt.Sprintf("&pull=%s", pull)
}
return modulebase.Post(this.ResourceManager, session, path, body, this.KeywordPlural)
}

View File

@@ -119,3 +119,7 @@ func (ucm *SUserCacheManager) FetchUserFromLoaclCache(ctx context.Context, q *sq
}
return users, nil
}
func (u *SUser) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return u.SUser.Delete(ctx, userCred)
}

View File

@@ -114,6 +114,7 @@ func (self *NotifyModelDispatcher) UpdateConfig(ctx context.Context, body jsonut
}
}
}
log.Debugf("update body: %s", data)
keys := data.SortedKeys()
config := make(map[string]string)
createDataList := make([]jsonutils.JSONObject, 0, len(keys))
@@ -131,6 +132,7 @@ func (self *NotifyModelDispatcher) UpdateConfig(ctx context.Context, body jsonut
}
// validate configs
log.Debugf("config: %#v", config)
isValid, message, err := models.NotifyService.ValidateConfig(ctx, contactType, config)
if err != nil {
if errors.Cause(err) != errors.ErrNotImplemented {
@@ -144,7 +146,7 @@ func (self *NotifyModelDispatcher) UpdateConfig(ctx context.Context, body jsonut
// create
for _, createData := range createDataList {
_, err := self.Create(ctx, jsonutils.JSONNull, createData, nil)
_, err := self.Create(ctx, jsonutils.NewDict(), createData, nil)
if err != nil {
return errors.Wrapf(err, "Create config %s for contact type %s failed", createData.String(), contactType)
}
@@ -155,31 +157,31 @@ func (self *NotifyModelDispatcher) UpdateConfig(ctx context.Context, body jsonut
return nil
}
func (self *NotifyModelDispatcher) ValidateConfig(ctx context.Context, contactType string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (self *NotifyModelDispatcher) ValidateConfig(ctx context.Context, contactType string, body jsonutils.JSONObject) error {
dict, ok := body.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("")
return httperrors.NewInputParameterError("")
}
dict = models.ConfigManager.Display2Database(contactType, dict)
configs := make(map[string]string)
for _, key := range dict.SortedKeys() {
value, err := dict.GetString(key)
if err != nil {
return nil, errors.Wrap(err, "jsonutils.JsonDict.GetString")
return errors.Wrap(err, "jsonutils.JsonDict.GetString")
}
configs[key] = value
}
isValid, message, err := models.NotifyService.ValidateConfig(ctx, contactType, configs)
if err != nil {
if errors.Cause(err) == errors.ErrNotImplemented {
return nil, httperrors.NewNotImplementedError("validating config of %s", contactType)
return httperrors.NewNotImplementedError("validating config of %s", contactType)
}
return nil, err
return err
}
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewBool(isValid), "is_valid")
ret.Add(jsonutils.NewString(message), "message")
return ret, nil
if isValid == false {
return httperrors.NewInputParameterError(message)
}
return nil
}
// CreateNotification create new notifications and send them through rpc.RpcService.
@@ -229,7 +231,7 @@ func (self *NotifyModelDispatcher) getIds(data jsonutils.JSONObject, key string)
}
ret = append(ret, id)
}
return ret[:len(ret):len(ret)]
return ret
}
// Verify process:
@@ -348,12 +350,14 @@ func (self *NotifyModelDispatcher) VerifyTrigger(ctx context.Context, params map
}
// DeleteContacts delete a group of contacts
func (self *NotifyModelDispatcher) DeleteContacts(ctx context.Context, uids2 []jsonutils.JSONObject) error {
func (self *NotifyModelDispatcher) DeleteContacts(ctx context.Context, uidArray []jsonutils.JSONObject) error {
// Get all id of uid
uids := make([]string, len(uids2))
for i := range uids2 {
uids[i] = strings.Trim(uids2[i].String(), `"`)
uids := make([]string, len(uidArray))
log.Debugf("uidArray: %s", uidArray)
for i := range uidArray {
uids[i], _ = uidArray[i].GetString()
}
log.Debugf("uids: %#v", uids)
uname := false
if v := ctx.Value("uname"); v != nil {
uname = true
@@ -370,6 +374,8 @@ func (self *NotifyModelDispatcher) DeleteContacts(ctx context.Context, uids2 []j
deleteFailed = append(deleteFailed, contact.ID)
}
}
// clean cache
noutils.DeleteUsers(ctx, userCred, uids)
if len(deleteFailed) != 0 {
errInfo := strings.Join(deleteFailed, ", ") + " ; these contact delete failed."
return errors.Error(errInfo)
@@ -379,7 +385,8 @@ func (self *NotifyModelDispatcher) DeleteContacts(ctx context.Context, uids2 []j
// UpdateContacts analysis the data and update corresponding contacts if they exist in the database create new ones.
func (self *NotifyModelDispatcher) UpdateContacts(ctx context.Context, idstr string, query jsonutils.JSONObject,
datas []jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (jsonutils.JSONObject, error) {
datas []jsonutils.JSONObject, pullCtypes []jsonutils.JSONObject, ctxIds []dispatcher.SResourceContext) (jsonutils.JSONObject,
error) {
type pair struct {
contact string
@@ -445,24 +452,56 @@ func (self *NotifyModelDispatcher) UpdateContacts(ctx context.Context, idstr str
// createFailed record the information of failed creation
createFailed := make([]string, 0, 1)
// Create contact info
newDatas := make([]map[string]interface{}, 0, len(contactInfos))
type CreateData struct {
UID string
ContactType string
Contact string
Enabled string
}
newDatas := make([]CreateData, 0, len(contactInfos))
for conType, conPair := range contactInfos {
tmpMap := map[string]interface{}{
"uid": idstr,
"contact_type": conType,
"contact": conPair.contact,
tmp := CreateData{
UID: idstr,
ContactType: conType,
Contact: conPair.contact,
}
if conPair.enabled != "-1" {
tmpMap["enabled"] = conPair.enabled
tmp.Enabled = conPair.enabled
}
newDatas = append(newDatas, tmpMap)
newDatas = append(newDatas, tmp)
}
pulls := make([]string, len(pullCtypes))
for i := range pullCtypes {
pulls[i], _ = pullCtypes[i].GetString()
}
if len(pulls) > 0 {
contacts, err := models.ContactManager.FetchByUIDAndCType(idstr, pulls)
if err != nil {
return nil, err
}
set := sets.NewString(pulls...)
for i := range contacts {
set.Delete(contacts[i].ContactType)
}
for _, ct := range set.UnsortedList() {
tmp := CreateData{
UID: idstr,
ContactType: ct,
Enabled: "1",
Contact: "user_id",
}
newDatas = append(newDatas, tmp)
}
}
log.Debugf("newDatas: %s", newDatas)
for _, newData := range newDatas {
_, err := self.Create(ctx, jsonutils.JSONNull, jsonutils.Marshal(newData), ctxIds)
_, err := self.Create(ctx, jsonutils.NewDict(), jsonutils.Marshal(newData), ctxIds)
if err != nil {
createFailed = append(createFailed, fmt.Sprintf(`uid:%q, contact_type:%q, contact:%q`, idstr,
newData["contact_type"], newData["contact"]))
newData.ContactType, newData.Contact))
}
}
@@ -485,10 +524,7 @@ func (self *NotifyModelDispatcher) UpdateContacts(ctx context.Context, idstr str
return nil, httperrors.NewGeneralError(errors.Error(errInfo))
}
if query.Contains("pull") {
cType, _ := query.GetString("pull")
models.PullContact(idstr, cType)
}
models.PullContact(idstr, pulls)
// keep the return value same as this of the GET interface
ret := jsonutils.NewDict()
@@ -497,6 +533,9 @@ func (self *NotifyModelDispatcher) UpdateContacts(ctx context.Context, idstr str
log.Errorf(err.Error())
return ret, nil
}
if len(contact) == 0 {
return nil, nil
}
outDetails, err := contact[0].GetExtraDetails(ctx, userCred, ret, false)
if err != nil {
log.Errorf(err.Error())

View File

@@ -55,6 +55,7 @@ func middleware(f appsrv.FilterHandler) appsrv.FilterHandler {
hander := func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
if _, ok := r.URL.Query()["uname"]; ok {
// Uname
log.Debugf("url.Query has a uname")
params := appctx.AppContextParams(ctx)
if uid, ok := params["<uid>"]; ok {
userDetail, err := utils.GetUserByIDOrName(ctx, uid)
@@ -62,6 +63,7 @@ func middleware(f appsrv.FilterHandler) appsrv.FilterHandler {
httperrors.NotFoundError(w, "Uid or Uname Not Found")
return
}
log.Debugf("find userDetail, id: %s, name: %s", userDetail.Id, userDetail.Name)
params["<uid>"] = userDetail.Id
}
ctx = context.WithValue(ctx, "uname", true)
@@ -256,12 +258,11 @@ func configValidateHandler(ctx context.Context, w http.ResponseWriter, r *http.R
httperrors.GeneralServerError(w, httperrors.NewInputParameterError("need config"))
}
ctype := params["<type>"]
res, err := manager.ValidateConfig(ctx, ctype, body)
err = manager.ValidateConfig(ctx, ctype, body)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
appsrv.SendJSON(w, res)
}
func notificationHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
@@ -275,12 +276,11 @@ func notificationHandler(ctx context.Context, w http.ResponseWriter, r *http.Req
httperrors.MissingParameterError(w, "gid | uid")
return
}
ret, err := manager.CreateNotification(ctx, data)
_, err = manager.CreateNotification(ctx, data)
if err != nil {
httperrors.GeneralServerError(w, err)
return
}
appsrv.SendJSON(w, ret)
}
// verify handler
@@ -304,14 +304,20 @@ func contactUpdateHandler(ctx context.Context, w http.ResponseWriter, r *http.Re
manager.Keyword(), manager.KeywordPlural()))
return
}
log.Debugf("data: %s", data)
pullCtypes, _ := body.GetArray(manager.Keyword(), "pull")
log.Debugf("pullCtypes: %s", pullCtypes)
uid := params["<uid>"]
out, err := manager.UpdateContacts(ctx, uid, mergeQueryParams(params, query), data, nil)
out, err := manager.UpdateContacts(ctx, uid, mergeQueryParams(params, query), data, pullCtypes, nil)
if err != nil {
log.Errorf(err.Error())
httperrors.BadRequestError(w, "")
return
}
if out == nil {
return
}
appsrv.SendJSON(w, wrap(out, manager.Keyword()))
}

View File

@@ -18,7 +18,9 @@ const (
EMAIL = "email"
MOBILE = "mobile"
DINGTALK = "dingtalk"
FEISHU = "feishu"
WEBCONSOLE = "webconsole"
ROBOT = "robot"
NOTIFY_RECEIVED = "received" // Received a task about sending a notification
NOTIFY_SENT = "sent" // Nofity module has sent notification, but result unkown
@@ -40,5 +42,6 @@ const (
// In webconsole, uid is the same as contact.
var UpdateNotAllow = map[string]struct{}{
DINGTALK: {},
FEISHU: {},
WEBCONSOLE: {},
}

View File

@@ -56,7 +56,7 @@ type SConfig struct {
Type string `width:"15" nullable:"false" create:"required" list:"user"`
KeyText string `width:"30" nullable:"false" create:"required" list:"user"`
ValueText string `width:"100" nullable:"false" create:"required" list:"user"`
ValueText string `width:"256" nullable:"false" create:"required" list:"user"`
}
// ListItemFilter is a hook function belong to IModelManager interface when Listing.

View File

@@ -56,7 +56,7 @@ func init() {
type SContact struct {
SStatusStandaloneResourceBase
UID string `width:"128" nullable:"false" create:"required" update:"user"`
UID string `width:"128" nullable:"false" create:"required" update:"user" list:"user" get:"user"`
ContactType string `width:"16" nullable:"false" create:"required" update:"user"`
Contact string `width:"64" nullable:"false" create:"required" update:"user"`
Enabled string `width:"5" nullable:"false" default:"1" create:"optional" update:"user"`
@@ -164,6 +164,7 @@ func (self *SContactManager) _UIDsFromUIDOrName(ctx context.Context, uidStrs []s
for _, uid = range uidSet.UnsortedList() {
uids = append(uids, uid)
}
log.Debugf("uids %s => %s", uidStrs, uids)
return uids, nil
}
@@ -205,7 +206,7 @@ func (self *SContact) getMoreDetail(ctx context.Context, userCred mcclient.Token
if err != nil {
return out, errors.Wrapf(err, "fetch Contacts of uid %s error", self.UID)
}
out.Id = self.UID
out.UID = self.UID
out.Name = uname
out.Details = jsonutils.Marshal(contacts).String()
@@ -224,13 +225,16 @@ func (manager *SContactManager) FetchCustomizeColumns(
stdRows := manager.SStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
var err error
for i := range rows {
rows[i] = api.ContactDetails{
ResourceBaseDetails: stdRows[i],
}
rows[i], _ = objs[i].(*SContact).getMoreDetail(ctx, userCred, rows[i])
rows[i], err = objs[i].(*SContact).getMoreDetail(ctx, userCred, rows[i])
if err != nil {
log.Errorf(err.Error())
}
}
return rows
}
@@ -281,16 +285,60 @@ func (self *SContactManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
if !scope.HigherEqual(rbacutils.ScopeSystem) {
q = q.Equals("uid", userCred.GetUserId())
}
q = q.GroupBy("uid")
q = q.GroupBy("uid").Desc("created_at")
return q, nil
}
// Contacts query all contacts by uids and contactType
func (self *SContactManager) Contacts(uids []string, contactType string) ([]SContact, error) {
contacts := make([]SContact, 0, len(uids))
if contactType == WEBCONSOLE {
for _, uid := range uids {
contacts = append(contacts, SContact{
UID: uid,
ContactType: WEBCONSOLE,
Contact: uid,
})
}
return contacts, nil
}
queryCon := contactType
if strings.Contains(contactType, ROBOT) {
queryCon = MOBILE
}
q := self.Query().Equals("contact_type", queryCon).Equals("enabled", "1").In("uid", uids)
err := db.FetchModelObjects(self, q, &contacts)
if err != nil {
return nil, err
}
// For Robot Sender, only one message of the same content is sent for multiple users,
// so the user's contact information is a collection of all contact information
if strings.Contains(contactType, ROBOT) {
// hack
contactVals := make([]string, len(contacts))
uidVals := make([]string, len(contacts))
for i := range contacts {
contactVals[i] = contacts[i].Contact
uidVals[i] = contacts[i].UID
}
contacts = []SContact{
{
UID: strings.Join(uidVals, ","),
ContactType: contactType,
Contact: strings.Join(contactVals, ","),
},
}
}
return contacts, nil
}
func (self *SContactManager) GetAllNotify(ctx context.Context, ids []string, contactType string, group bool) ([]SContact, error) {
var uids []string
var err error
q := self.Query()
if !group {
if v := ctx.Value("uname"); v != nil {
ids, err = self._UIDsFromUIDOrName(ctx, ids)
@@ -310,26 +358,7 @@ func (self *SContactManager) GetAllNotify(ctx context.Context, ids []string, con
}
uids = uid
}
q.Filter(sqlchemy.AND(sqlchemy.In(q.Field("uid"), uids), sqlchemy.Equals(q.Field("contact_type"),
contactType), sqlchemy.Equals(q.Field("status"), CONTACT_VERIFIED)))
if contactType == WEBCONSOLE {
ret := make([]SContact, len(uids))
for i := range uids {
ret[i] = SContact{
UID: uids[i],
ContactType: WEBCONSOLE,
Contact: uids[i],
}
}
return ret, nil
}
contacts := make([]SContact, 0, 2)
err = db.FetchModelObjects(self, q, &contacts)
if err != nil {
return nil, err
}
return contacts, nil
return self.Contacts(uids, contactType)
}
type SContactResponse struct {

View File

@@ -27,6 +27,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
@@ -208,3 +209,20 @@ func (manager *STemplateManager) ValidateCreateData(ctx context.Context, userCre
}
return data, nil
}
func (self *STemplateManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
queryDict := query.(*jsonutils.JSONDict)
if queryDict.Contains("topic") {
val, _ := queryDict.GetString("topic")
q = q.Equals("topic", val)
}
if queryDict.Contains("template_type") {
val, _ := queryDict.GetString("template_type")
q = q.Equals("template_type", val)
}
if queryDict.Contains("contact_type") {
val, _ := queryDict.GetString("contact_type")
q = q.Equals("contact_type", val)
}
return q, nil
}

View File

@@ -39,8 +39,9 @@ func init() {
func Send(notifications []*SNotification, userCred mcclient.TokenCredential, contacts []string) {
for i := range notifications {
notification, contact := notifications[i], contacts[i]
workMan.Run(func() {
sendone(context.Background(), userCred, notifications[i], contacts[i])
sendone(context.Background(), userCred, notification, contact)
}, nil, nil)
}
}
@@ -108,10 +109,13 @@ func SendVerifyMessage(ctx context.Context, userCred mcclient.TokenCredential, v
return nil
}
func PullContact(uid string, contactType string) {
workMan.Run(func() {
pullContact(context.Background(), uid, contactType)
}, nil, nil)
func PullContact(uid string, contactTypes []string) {
for i := range contactTypes {
ct := contactTypes[i]
workMan.Run(func() {
pullContact(context.Background(), uid, ct)
}, nil, nil)
}
}
func pullContact(ctx context.Context, uid string, contactType string) {
@@ -143,6 +147,10 @@ func pullContact(ctx context.Context, uid string, contactType string) {
origin := subContact.Contact
_, err := db.Update(subContact, func() error {
subContact.Contact = userid
subContact.VerifiedAt = time.Now()
if subContact.Status != CONTACT_VERIFIED {
subContact.Status = CONTACT_VERIFIED
}
return nil
})
if err != nil {

View File

@@ -17,8 +17,10 @@ package utils
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/notify/cache"
)
@@ -28,10 +30,24 @@ func GetUserByIDOrName(ctx context.Context, idStr string) (*cache.SUser, error)
func GetUsersWithoutRemote(ctx context.Context, idStr []string) ([]cache.SUser, error) {
q := cache.UserCacheManager.Query()
q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("id"), idStr), sqlchemy.In(q.Field("name"), idStr)))
q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("id"), idStr), sqlchemy.In(q.Field("name"), idStr))).Desc("updated_at")
return cache.UserCacheManager.FetchUserFromLoaclCache(ctx, q)
}
func DeleteUsers(ctx context.Context, userCred mcclient.TokenCredential, ids []string) error {
users, err := GetUsersWithoutRemote(ctx, ids)
if err != nil {
return err
}
for i := range users {
err := users[i].Delete(ctx, userCred)
if err != nil {
return errors.Wrapf(err, "delete cache.SUser %s error", users[i].Id)
}
}
return nil
}
func GetUserIdsLikeName(ctx context.Context, name string) ([]string, error) {
users, err := cache.UserCacheManager.FetchUserLikeName(ctx, name, true)
if err != nil {