feat: expose email and sms APIs as services to SDK (#202)

Signed-off-by: Kininaru <shiftregister233@outlook.com>

invalid receivers
This commit is contained in:
Kininaru 2021-07-30 14:15:10 +08:00 committed by GitHub
parent 512a451800
commit 7a2230f63e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 187 additions and 5 deletions

159
controllers/service.go Normal file
View File

@ -0,0 +1,159 @@
// Copyright 2021 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Casdoor will expose its providers as services to SDK
// We are going to implement those services as APIs here
package controllers
import (
"encoding/json"
"github.com/casbin/casdoor/object"
"github.com/casbin/casdoor/util"
sender "github.com/casdoor/go-sms-sender"
)
// @Title SendEmail
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
// @Param clientId query string true "The clientId of the application"
// @Param clientSecret query string true "The clientSecret of the application"
// @Param body body emailForm true "Details of the email request"
// @Success 200 {object} Response object
// @router /api/send-email [post]
func (c *ApiController) SendEmail() {
clientId := c.Input().Get("clientId")
clientSecret := c.Input().Get("clientSecret")
app := object.GetApplicationByClientIdAndSecret(clientId, clientSecret)
if app == nil {
c.ResponseError("Invalid clientId or clientSecret.")
return
}
provider := app.GetEmailProvider()
if provider == nil {
c.ResponseError("No Email provider for this application.")
return
}
var emailForm struct {
Title string `json:"title"`
Content string `json:"content"`
Receivers []string `json:"receivers"`
Sender string `json:"sender"`
}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &emailForm)
if err != nil {
c.ResponseError("Request body error.")
return
}
if util.IsStrsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
c.ResponseError("Missing parameters.")
return
}
var invalidEmails []string
for _, receiver := range emailForm.Receivers {
if !util.IsEmailValid(receiver) {
invalidEmails = append(invalidEmails, receiver)
}
}
if len(invalidEmails) != 0 {
c.ResponseError("Invalid Email addresses", invalidEmails)
return
}
ok := 0
for _, receiver := range emailForm.Receivers {
if msg := object.SendEmail(
provider,
emailForm.Title,
emailForm.Content,
receiver,
emailForm.Sender);
len(msg) == 0 {
ok++
}
}
c.Data["json"] = Response{Status: "ok", Data: ok}
c.ServeJSON()
}
// @Title SendSms
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
// @Param clientId query string true "The clientId of the application"
// @Param clientSecret query string true "The clientSecret of the application"
// @Param body body smsForm true "Details of the sms request"
// @Success 200 {object} Response object
// @router /api/send-sms [post]
func (c *ApiController) SendSms() {
clientId := c.Input().Get("clientId")
clientSecret := c.Input().Get("clientSecret")
app := object.GetApplicationByClientIdAndSecret(clientId, clientSecret)
if app == nil {
c.ResponseError("Invalid clientId or clientSecret.")
return
}
provider := app.GetSmsProvider()
if provider == nil {
c.ResponseError("No SMS provider for this application.")
return
}
client := sender.NewSmsClient(
provider.Type,
provider.ClientId,
provider.ClientSecret,
provider.SignName,
provider.RegionId,
provider.TemplateCode,
provider.AppId,
)
if client == nil {
c.ResponseError("Invalid provider info.")
return
}
var smsForm struct {
Receivers []string `json:"receivers"`
Parameters map[string]string `json:"parameters"`
}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &smsForm)
if err != nil {
c.ResponseError("Request body error.")
return
}
var invalidReceivers []string
for _, receiver := range smsForm.Receivers {
if !util.IsPhoneCnValid(receiver) {
invalidReceivers = append(invalidReceivers, receiver)
}
}
if len(invalidReceivers) != 0{
c.ResponseError("Invalid phone numbers", invalidReceivers)
return
}
client.SendMessage(smsForm.Parameters, smsForm.Receivers...)
c.Data["json"] = Response{Status: "ok"}
c.ServeJSON()
}

View File

@ -49,8 +49,16 @@ func InitHttpClient() {
//println("Response status: %s", resp.Status)
}
func (c *ApiController) ResponseError(error string) {
c.Data["json"] = Response{Status: "error", Msg: error}
func (c *ApiController) ResponseError(error string, data ...interface{}) {
resp := Response{Status: "error", Msg: error}
switch len(data) {
case 2:
resp.Data2 = data[1]
fallthrough
case 1:
resp.Data = data[0]
}
c.Data["json"] = resp
c.ServeJSON()
}

View File

@ -142,6 +142,19 @@ func GetApplicationByClientId(clientId string) *Application {
}
}
func GetApplicationByClientIdAndSecret(clientId, clientSecret string) *Application {
if util.IsStrsEmpty(clientId, clientSecret) {
return nil
}
app := GetApplicationByClientId(clientId)
if app == nil || app.ClientSecret != clientSecret {
return nil
}
return app
}
func GetApplication(id string) *Application {
owner, name := util.GetOwnerAndNameFromId(id)
return getApplication(owner, name)

View File

@ -33,9 +33,8 @@ type Object struct {
}
func getUsernameByClientIdSecret(ctx *context.Context) string {
requestUri := ctx.Request.RequestURI
clientId := parseQuery(requestUri, "clientId")
clientSecret := parseQuery(requestUri, "clientSecret")
clientId := ctx.Input.Query("clientId")
clientSecret := ctx.Input.Query("clientSecret")
if len(clientId) == 0 || len(clientSecret) == 0 {
return ""
}

View File

@ -95,5 +95,8 @@ func initAPI() {
beego.Router("/api/get-records", &controllers.ApiController{}, "GET:GetRecords")
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
}