diff --git a/pkg/apis/notify/receiver.go b/pkg/apis/notify/receiver.go index 7b77461971..0d58a8af47 100644 --- a/pkg/apis/notify/receiver.go +++ b/pkg/apis/notify/receiver.go @@ -15,6 +15,9 @@ package notify import ( + "fmt" + "regexp" + "yunion.io/x/onecloud/pkg/apis" ) @@ -35,20 +38,50 @@ type ReceiverCreateInput struct { // example: example@gmail.com Email string `json:"email"` - // description: user mobile - // example: 17812345678 - Mobile string `json:"mobile"` + InternationalMobile SInternationalMobile `json:"international_mobile"` // description: enabled contact types for user // example: {"email", "mobile", "feishu", "dingtalk", "workwx"} EnabledContactTypes []string `json:"enabled_contact_types"` } +type SInternationalMobile struct { + // description: user mobile + // example: 17812345678 + Mobile string `json:"mobile"` + // description: area code of mobile + // example: 86 + AreaCode string `json:"area_code"` +} + +var pareser = regexp.MustCompile(`\+(\d*) (.*)`) + +func ParseInternationalMobile(mobile string) SInternationalMobile { + matchs := pareser.FindStringSubmatch(mobile) + if len(matchs) == 0 { + return SInternationalMobile{ + Mobile: mobile, + } + } + return SInternationalMobile{ + Mobile: matchs[2], + AreaCode: matchs[1], + } +} + +func (im SInternationalMobile) String() string { + if im.AreaCode == "" { + return im.Mobile + } + return fmt.Sprintf("+%s %s", im.AreaCode, im.Mobile) +} + type ReceiverDetails struct { apis.StatusStandaloneResourceDetails apis.DomainizedResourceInfo SReceiver + InternationalMobile SInternationalMobile `json:"international_mobile"` // description: enabled contact types for user // example: eamil, mobile, feishu, dingtalk, workwx @@ -85,9 +118,7 @@ type ReceiverUpdateInput struct { // example: example@gmail.com Email string `json:"email"` - // description: user mobile - // example: 17812345678 - Mobile string `json:"mobile"` + InternationalMobile SInternationalMobile `json:"international_mobile"` // description: enabled contacts for user // example: {"email", "mobile", "feishu", "dingtalk", "workwx"} diff --git a/pkg/apis/notify/zz_generated.model.go b/pkg/apis/notify/zz_generated.model.go index 86bbf7920b..41eee9f652 100644 --- a/pkg/apis/notify/zz_generated.model.go +++ b/pkg/apis/notify/zz_generated.model.go @@ -45,8 +45,7 @@ type SReceiver struct { apis.SStatusStandaloneResourceBase apis.SDomainizedResourceBase apis.SEnabledResourceBase - Email string `json:"email"` - Mobile string `json:"mobile"` + Email string `json:"email"` // swagger:ignore EnabledEmail *bool `json:"enabled_email,omitempty"` // swagger:ignore diff --git a/pkg/mcclient/modules/mod_notify.go b/pkg/mcclient/modules/mod_notify.go index c55bda3759..6ac0e1a4f9 100644 --- a/pkg/mcclient/modules/mod_notify.go +++ b/pkg/mcclient/modules/mod_notify.go @@ -32,7 +32,7 @@ func init() { NotifyReceiver = NewNotifyv2Manager( "receiver", "receivers", - []string{"ID", "Name", "Email", "Mobile", "Enabled_Contact_Types", "Verified_Infos"}, + []string{"ID", "Name", "Email", "International_Mobile", "Enabled_Contact_Types", "Verified_Infos"}, []string{}, ) register(&NotifyReceiver) diff --git a/pkg/mcclient/options/notify/receiver.go b/pkg/mcclient/options/notify/receiver.go index dfb08b1d9c..2954e30b93 100644 --- a/pkg/mcclient/options/notify/receiver.go +++ b/pkg/mcclient/options/notify/receiver.go @@ -22,11 +22,18 @@ type ReceiverCreateOptions struct { UID string `help:"user id in keystone"` Email string `help:"email of receiver"` Mobile string `help:"mobile of receiver"` + MobileAreaCode string `help:"area code of mobile"` EnabledContactTypes []string `help:"enabled contact type"` } func (rc *ReceiverCreateOptions) Params() (jsonutils.JSONObject, error) { - return options.StructToParams(rc) + d := jsonutils.NewDict() + d.Set("uid", jsonutils.NewString(rc.UID)) + d.Set("email", jsonutils.NewString(rc.Email)) + d.Set("enabled_contact_type", jsonutils.NewStringArray(rc.EnabledContactTypes)) + d.Add(jsonutils.NewString(rc.Mobile), "international_mobile", "mobile") + d.Add(jsonutils.NewString(rc.MobileAreaCode), "international_mobile", "area_code") + return d, nil } type ReceiverOptions struct { @@ -43,44 +50,54 @@ func (r *ReceiverOptions) Params() (jsonutils.JSONObject, error) { type ReceiverUpdateOptions struct { ReceiverOptions - receiverUpdateOptions + SreceiverUpdateOptions } -type receiverUpdateOptions struct { +type SreceiverUpdateOptions struct { Email string `help:"email of receiver"` Mobile string `help:"mobile of receiver"` + MobileAreaCode string `help:"area code of mobile"` EnabledContactType []string `help:"enabled contact type"` } func (ru *ReceiverUpdateOptions) Params() (jsonutils.JSONObject, error) { - return jsonutils.Marshal(ru.receiverUpdateOptions), nil + d := jsonutils.NewDict() + if len(ru.Email) > 0 { + d.Set("email", jsonutils.NewString(ru.Email)) + } + d.Set("enabled_contact_types", jsonutils.NewStringArray(ru.EnabledContactType)) + if len(ru.Mobile) > 0 { + d.Add(jsonutils.NewString(ru.Mobile), "international_mobile", "mobile") + d.Add(jsonutils.NewString(ru.MobileAreaCode), "international_mobile", "area_code") + } + return d, nil } type ReceiverTriggerVerifyOptions struct { ReceiverOptions - receiverTriggerVerifyOptions + SreceiverTriggerVerifyOptions } -type receiverTriggerVerifyOptions struct { +type SreceiverTriggerVerifyOptions struct { ContactType string `help:"Contact type to trigger verify" choices:"email|mobile"` } func (rt *ReceiverTriggerVerifyOptions) Params() (jsonutils.JSONObject, error) { - return jsonutils.Marshal(rt.receiverTriggerVerifyOptions), nil + return jsonutils.Marshal(rt.SreceiverTriggerVerifyOptions), nil } type ReceiverVerifyOptions struct { ReceiverOptions - receiverVerifyOptions + SreceiverVerifyOptions } -type receiverVerifyOptions struct { +type SreceiverVerifyOptions struct { ContactType string `help:"Contact type to trigger verify" choices:"email|mobile"` Token string `help:"Token from verify message sent to you"` } func (rv *ReceiverVerifyOptions) Params() (jsonutils.JSONObject, error) { - return jsonutils.Marshal(rv.receiverVerifyOptions), nil + return jsonutils.Marshal(rv.SreceiverVerifyOptions), nil } type ReceiverIntellijGetOptions struct { diff --git a/pkg/notify/models/receiver.go b/pkg/notify/models/receiver.go index 666e69c0d9..10a5e0eeeb 100644 --- a/pkg/notify/models/receiver.go +++ b/pkg/notify/models/receiver.go @@ -97,8 +97,9 @@ type SReceiver struct { db.SDomainizedResourceBase db.SEnabledResourceBase - Email string `width:"64" nullable:"false" create:"optional" update:"user" get:"user" list:"user"` - Mobile string `width:"16" nullable:"false" create:"optional" update:"user" get:"user" list:"user"` + Email string `width:"64" nullable:"false" create:"optional" update:"user" get:"user" list:"user"` + // swagger:ignore + Mobile string `width:"32" nullable:"false" create:"optional"` Lang string `width:"8" charset:"ascii" nullable:"false" list:"user" update:"user"` // swagger:ignore @@ -280,7 +281,7 @@ func (rm *SReceiverManager) ValidateCreateData(ctx context.Context, userCred mcc return input, httperrors.NewInputParameterError("invalid email") } // validate mobile - if ok := LaxMobileRegexp.MatchString(input.Mobile); len(input.Mobile) > 0 && !ok { + if ok := LaxMobileRegexp.MatchString(input.InternationalMobile.Mobile); len(input.InternationalMobile.Mobile) > 0 && !ok { return input, httperrors.NewInputParameterError("invalid mobile") } return input, nil @@ -601,6 +602,7 @@ func (rm *SReceiverManager) FetchCustomizeColumns(ctx context.Context, userCred rows[i].StatusStandaloneResourceDetails = sRows[i] rows[i].DomainizedResourceInfo = dRows[i] user := objs[i].(*SReceiver) + rows[i].InternationalMobile = api.ParseInternationalMobile(user.Mobile) if enabledCTs, err := user.GetEnabledContactTypes(); err != nil { log.Errorf("GetEnabledContactTypes: %v", err) } else { @@ -662,6 +664,7 @@ func (r *SReceiver) CustomizeCreate(ctx context.Context, userCred mcclient.Token if input.Enabled == nil { r.Enabled = tristate.True } + r.Mobile = input.InternationalMobile.String() err = r.SetEnabledContactTypes(input.EnabledContactTypes) if err != nil { return errors.Wrap(err, "SetEnabledContactTypes") @@ -684,7 +687,7 @@ func (r *SReceiver) ValidateUpdateData(ctx context.Context, userCred mcclient.To return input, httperrors.NewInputParameterError("invalid email") } // validate mobile - if ok := len(input.Mobile) == 0 || LaxMobileRegexp.MatchString(input.Mobile); !ok { + if ok := len(input.InternationalMobile.Mobile) == 0 || LaxMobileRegexp.MatchString(input.InternationalMobile.Mobile); !ok { return input, httperrors.NewInputParameterError("invalid mobile") } return input, nil @@ -702,6 +705,9 @@ func (r *SReceiver) PreUpdate(ctx context.Context, userCred mcclient.TokenCreden log.Errorf("PullCache: %v", err) } err = r.SetEnabledContactTypes(input.EnabledContactTypes) + if err != nil { + log.Errorf("unable to SetEnabledContactTypes") + } if len(input.Email) != 0 && input.Email != r.Email { r.VerifiedEmail = tristate.False for _, c := range r.subContactCache { @@ -711,8 +717,10 @@ func (r *SReceiver) PreUpdate(ctx context.Context, userCred mcclient.TokenCreden } } } - if len(input.Mobile) != 0 && input.Mobile != r.Mobile { + mobile := input.InternationalMobile.String() + if len(mobile) != 0 && mobile != r.Mobile { r.VerifiedMobile = tristate.False + r.Mobile = mobile for _, c := range r.subContactCache { if c.ParentContactType == api.MOBILE { c.Verified = tristate.False diff --git a/pkg/notify/rpc/send.go b/pkg/notify/rpc/send.go index 4b0710f5b8..35e1c25394 100644 --- a/pkg/notify/rpc/send.go +++ b/pkg/notify/rpc/send.go @@ -31,6 +31,7 @@ import ( "yunion.io/x/log" "yunion.io/x/pkg/errors" + api "yunion.io/x/onecloud/pkg/apis/notify" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/notify" notifyv2 "yunion.io/x/onecloud/pkg/notify" @@ -176,6 +177,11 @@ func (self *SRpcService) RestartService(ctx context.Context, config notifyv2.SCo func (self *SRpcService) ContactByMobile(ctx context.Context, mobile, serviceName string) (string, error) { + iMobile := api.ParseInternationalMobile(mobile) + // compatible + if iMobile.AreaCode == "86" { + mobile = iMobile.Mobile + } args := apis.UseridByMobileParams{} args.Mobile = mobile