mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 07:50:25 +08:00 
			
		
		
		
	增加CORS自适应跨域
This commit is contained in:
		@@ -182,19 +182,19 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := &shared.HTTPHeaderPolicy{}
 | 
			
		||||
	var config = &shared.HTTPHeaderPolicy{}
 | 
			
		||||
	config.Id = int64(policy.Id)
 | 
			
		||||
	config.IsOn = policy.IsOn
 | 
			
		||||
 | 
			
		||||
	// SetHeaders
 | 
			
		||||
	if IsNotNull(policy.SetHeaders) {
 | 
			
		||||
		refs := []*shared.HTTPHeaderRef{}
 | 
			
		||||
		var refs = []*shared.HTTPHeaderRef{}
 | 
			
		||||
		err = json.Unmarshal(policy.SetHeaders, &refs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if len(refs) > 0 {
 | 
			
		||||
			resultRefs := []*shared.HTTPHeaderRef{}
 | 
			
		||||
			var resultRefs = []*shared.HTTPHeaderRef{}
 | 
			
		||||
			for _, ref := range refs {
 | 
			
		||||
				headerConfig, err := SharedHTTPHeaderDAO.ComposeHeaderConfig(tx, ref.HeaderId)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
@@ -212,7 +212,7 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
 | 
			
		||||
 | 
			
		||||
	// Delete Headers
 | 
			
		||||
	if IsNotNull(policy.DeleteHeaders) {
 | 
			
		||||
		headers := []string{}
 | 
			
		||||
		var headers = []string{}
 | 
			
		||||
		err = json.Unmarshal(policy.DeleteHeaders, &headers)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
@@ -220,6 +220,16 @@ func (this *HTTPHeaderPolicyDAO) ComposeHeaderPolicyConfig(tx *dbs.Tx, headerPol
 | 
			
		||||
		config.DeleteHeaders = headers
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// CORS
 | 
			
		||||
	if IsNotNull(policy.Cors) {
 | 
			
		||||
		var corsConfig = &shared.HTTPCORSHeaderConfig{}
 | 
			
		||||
		err = json.Unmarshal(policy.Cors, corsConfig)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		config.CORS = corsConfig
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Expires
 | 
			
		||||
	// TODO
 | 
			
		||||
 | 
			
		||||
@@ -235,6 +245,46 @@ func (this *HTTPHeaderPolicyDAO) FindHeaderPolicyIdWithHeaderId(tx *dbs.Tx, head
 | 
			
		||||
		FindInt64Col(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateHeaderPolicyCORS 修改CORS
 | 
			
		||||
func (this *HTTPHeaderPolicyDAO) UpdateHeaderPolicyCORS(tx *dbs.Tx, headerPolicyId int64, corsConfig *shared.HTTPCORSHeaderConfig) error {
 | 
			
		||||
	if headerPolicyId <= 0 {
 | 
			
		||||
		return errors.New("invalid headerId")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	corsJSON, err := json.Marshal(corsConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = this.Query(tx).
 | 
			
		||||
		Pk(headerPolicyId).
 | 
			
		||||
		Set("cors", corsJSON).
 | 
			
		||||
		UpdateQuickly()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return this.NotifyUpdate(tx, headerPolicyId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CheckUserHeaderPolicy 检查用户权限
 | 
			
		||||
func (this *HTTPHeaderPolicyDAO) CheckUserHeaderPolicy(tx *dbs.Tx, userId int64, policyId int64) error {
 | 
			
		||||
	if userId <= 0 || policyId <= 0 {
 | 
			
		||||
		return ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithHeaderPolicyId(tx, policyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if webId <= 0 {
 | 
			
		||||
		return ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return SharedHTTPWebDAO.CheckUserWeb(tx, userId, webId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotifyUpdate 通知更新
 | 
			
		||||
func (this *HTTPHeaderPolicyDAO) NotifyUpdate(tx *dbs.Tx, policyId int64) error {
 | 
			
		||||
	webId, err := SharedHTTPWebDAO.FindEnabledWebIdWithHeaderPolicyId(tx, policyId)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ package models
 | 
			
		||||
 | 
			
		||||
import "github.com/iwind/TeaGo/dbs"
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// HTTPHeaderPolicy Header定义
 | 
			
		||||
type HTTPHeaderPolicy struct {
 | 
			
		||||
	Id             uint32   `field:"id"`             // ID
 | 
			
		||||
	IsOn           bool     `field:"isOn"`           // 是否启用
 | 
			
		||||
@@ -16,21 +16,23 @@ type HTTPHeaderPolicy struct {
 | 
			
		||||
	ReplaceHeaders dbs.JSON `field:"replaceHeaders"` // 替换Header内容
 | 
			
		||||
	Expires        dbs.JSON `field:"expires"`        // Expires单独设置
 | 
			
		||||
	DeleteHeaders  dbs.JSON `field:"deleteHeaders"`  // 删除的Headers
 | 
			
		||||
	Cors           dbs.JSON `field:"cors"`           // CORS配置
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HTTPHeaderPolicyOperator struct {
 | 
			
		||||
	Id             interface{} // ID
 | 
			
		||||
	IsOn           interface{} // 是否启用
 | 
			
		||||
	State          interface{} // 状态
 | 
			
		||||
	AdminId        interface{} // 管理员ID
 | 
			
		||||
	UserId         interface{} // 用户ID
 | 
			
		||||
	CreatedAt      interface{} // 创建时间
 | 
			
		||||
	AddHeaders     interface{} // 添加的Header
 | 
			
		||||
	AddTrailers    interface{} // 添加的Trailers
 | 
			
		||||
	SetHeaders     interface{} // 设置Header
 | 
			
		||||
	ReplaceHeaders interface{} // 替换Header内容
 | 
			
		||||
	Expires        interface{} // Expires单独设置
 | 
			
		||||
	DeleteHeaders  interface{} // 删除的Headers
 | 
			
		||||
	Id             any // ID
 | 
			
		||||
	IsOn           any // 是否启用
 | 
			
		||||
	State          any // 状态
 | 
			
		||||
	AdminId        any // 管理员ID
 | 
			
		||||
	UserId         any // 用户ID
 | 
			
		||||
	CreatedAt      any // 创建时间
 | 
			
		||||
	AddHeaders     any // 添加的Header
 | 
			
		||||
	AddTrailers    any // 添加的Trailers
 | 
			
		||||
	SetHeaders     any // 设置Header
 | 
			
		||||
	ReplaceHeaders any // 替换Header内容
 | 
			
		||||
	Expires        any // Expires单独设置
 | 
			
		||||
	DeleteHeaders  any // 删除的Headers
 | 
			
		||||
	Cors           any // CORS配置
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHTTPHeaderPolicyOperator() *HTTPHeaderPolicyOperator {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,9 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/db/models"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type HTTPHeaderPolicyService struct {
 | 
			
		||||
@@ -13,16 +15,22 @@ type HTTPHeaderPolicyService struct {
 | 
			
		||||
 | 
			
		||||
// FindEnabledHTTPHeaderPolicyConfig 查找策略配置
 | 
			
		||||
func (this *HTTPHeaderPolicyService) FindEnabledHTTPHeaderPolicyConfig(ctx context.Context, req *pb.FindEnabledHTTPHeaderPolicyConfigRequest) (*pb.FindEnabledHTTPHeaderPolicyConfigResponse, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config, err := models.SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(tx, req.HeaderPolicyId)
 | 
			
		||||
	config, err := models.SharedHTTPHeaderPolicyDAO.ComposeHeaderPolicyConfig(tx, req.HttpHeaderPolicyId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -32,7 +40,7 @@ func (this *HTTPHeaderPolicyService) FindEnabledHTTPHeaderPolicyConfig(ctx conte
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &pb.FindEnabledHTTPHeaderPolicyConfigResponse{HeaderPolicyJSON: configData}, nil
 | 
			
		||||
	return &pb.FindEnabledHTTPHeaderPolicyConfigResponse{HttpHeaderPolicyJSON: configData}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateHTTPHeaderPolicy 创建策略
 | 
			
		||||
@@ -44,28 +52,32 @@ func (this *HTTPHeaderPolicyService) CreateHTTPHeaderPolicy(ctx context.Context,
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
 | 
			
		||||
	headerPolicyId, err := models.SharedHTTPHeaderPolicyDAO.CreateHeaderPolicy(tx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &pb.CreateHTTPHeaderPolicyResponse{HeaderPolicyId: headerPolicyId}, nil
 | 
			
		||||
	return &pb.CreateHTTPHeaderPolicyResponse{HttpHeaderPolicyId: headerPolicyId}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicyAddingHeaders 修改AddHeaders
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingHeadersRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -75,16 +87,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingHeaders(ctx con
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicySettingHeaders 修改SetHeaders
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicySettingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicySettingHeadersRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateSettingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateSettingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -94,16 +112,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicySettingHeaders(ctx co
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicyAddingTrailers 修改AddTrailers
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingTrailers(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyAddingTrailersRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingTrailers(tx, req.HeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateAddingTrailers(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -113,16 +137,22 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyAddingTrailers(ctx co
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicyReplacingHeaders 修改ReplaceHeaders
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyReplacingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyReplacingHeadersRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateReplacingHeaders(tx, req.HeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateReplacingHeaders(tx, req.HttpHeaderPolicyId, req.HeadersJSON)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -132,16 +162,57 @@ func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyReplacingHeaders(ctx
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicyDeletingHeaders 修改删除的Headers
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyDeletingHeaders(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyDeletingHeadersRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, _, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// TODO 检查权限
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateDeletingHeaders(tx, req.HeaderPolicyId, req.HeaderNames)
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateDeletingHeaders(tx, req.HttpHeaderPolicyId, req.HeaderNames)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateHTTPHeaderPolicyCORS 修改策略CORS设置
 | 
			
		||||
func (this *HTTPHeaderPolicyService) UpdateHTTPHeaderPolicyCORS(ctx context.Context, req *pb.UpdateHTTPHeaderPolicyCORSRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, userId, err := this.ValidateAdminAndUser(ctx, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
 | 
			
		||||
	// 检查权限
 | 
			
		||||
	if userId > 0 {
 | 
			
		||||
		err = models.SharedHTTPHeaderPolicyDAO.CheckUserHeaderPolicy(tx, userId, req.HttpHeaderPolicyId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var corsConfig = &shared.HTTPCORSHeaderConfig{}
 | 
			
		||||
	err = json.Unmarshal(req.CorsJSON, corsConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	err = corsConfig.Init()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("validate CORS config failed: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = models.SharedHTTPHeaderPolicyDAO.UpdateHeaderPolicyCORS(tx, req.HttpHeaderPolicyId, corsConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user