initial crm server
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
// 数据库表名
|
||||
USER = "user"
|
||||
CUSTOMER = "customer"
|
||||
CONTRACT = "contract"
|
||||
PRODUCT = "product"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
// RestPage 分页查询
|
||||
// page 设置起始页、每页条数,
|
||||
// name 查询目标表的名称
|
||||
// query 查询条件,
|
||||
// dest 查询结果绑定的结构体,
|
||||
// bind 绑定表结构对应的结构体
|
||||
func restPage(page models.Page, name string, query interface{}, dest interface{}, bind interface{}) (int64, error) {
|
||||
if page.PageNum > 0 && page.PageSize > 0 {
|
||||
offset := (page.PageNum - 1) * page.PageSize
|
||||
global.Db.Offset(offset).Limit(page.PageSize).Table(name).Where(query).Find(dest)
|
||||
}
|
||||
res := global.Db.Table(name).Where(query).Find(bind)
|
||||
return res.RowsAffected, res.Error
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
"crm/response"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ContractService struct {
|
||||
}
|
||||
|
||||
// 创建合同
|
||||
func (c *ContractService) Create(param *models.ContractCreateParam) int {
|
||||
contract := models.Contract{
|
||||
Name: param.Name,
|
||||
Amount: param.Amount,
|
||||
BeginTime: param.BeginTime,
|
||||
OverTime: param.OverTime,
|
||||
Remarks: param.Remarks,
|
||||
Cid: param.Cid,
|
||||
Productlist: param.Productlist,
|
||||
Status: param.Status,
|
||||
Creator: param.Creator,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
if err := global.Db.Create(&contract).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 更新合同
|
||||
func (c *ContractService) Update(param *models.ContractUpdateParam) int {
|
||||
contract := models.Contract{
|
||||
Id: param.Id,
|
||||
Name: param.Name,
|
||||
Amount: param.Amount,
|
||||
BeginTime: param.BeginTime,
|
||||
OverTime: param.OverTime,
|
||||
Remarks: param.Remarks,
|
||||
Cid: param.Cid,
|
||||
Productlist: param.Productlist,
|
||||
Status: param.Status,
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err := global.Db.Model(&contract).Updates(&contract).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 删除合同
|
||||
func (c *ContractService) Delete(param *models.ContractDeleteParam) int {
|
||||
if err := global.Db.Delete(&models.Contract{}, param.Ids).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询合同列表
|
||||
func (c *ContractService) QueryList(param *models.ContractQueryParam) ([]*models.ContractList, int64, int) {
|
||||
contractList := make([]*models.ContractList, 0)
|
||||
s := "contract.id, contract.name, contract.amount, contract.begin_time, contract.over_time, customer.name as cname, contract.remarks, contract.status, contract.created, contract.updated"
|
||||
j := "inner join customer on contract.cid = customer.id and contract.creator = ?"
|
||||
|
||||
// 分页查询
|
||||
offset := (param.Page.PageNum - 1) * param.Page.PageSize
|
||||
mdb := global.Db.Offset(offset).Limit(param.Page.PageSize).Table(CONTRACT).Select(s)
|
||||
var err error
|
||||
if param.Id != 0 {
|
||||
err = mdb.Joins(j+" and contract.id = ?", param.Creator, param.Id).Scan(&contractList).Error
|
||||
} else {
|
||||
err = mdb.Joins(j, param.Creator).Scan(&contractList).Error
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, response.ErrCodeFailed
|
||||
}
|
||||
var rows int64
|
||||
global.Db.Raw("select count(*) from contract where creator = ?", param.Creator).Scan(&rows)
|
||||
return contractList, rows, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询合同信息
|
||||
func (c *ContractService) QueryInfo(param *models.ContractQueryParam) (*models.ContractInfo, int) {
|
||||
contract := models.Contract{
|
||||
Id: param.Id,
|
||||
}
|
||||
contractInfo := models.ContractInfo{}
|
||||
err := global.Db.Table(CONTRACT).Where(&contract).First(&contractInfo).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return &contractInfo, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 在编辑合同中,添加产品后,增加已添加的产品列表
|
||||
func (p *ContractService) QueryPlist(param *models.ProductQueryParam) ([]*models.Products, int) {
|
||||
products := make([]*models.Products, 0)
|
||||
err := global.Db.Table(PRODUCT).Find(&products, param.Ids).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return products, response.ErrCodeSuccess
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
"crm/response"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CustomerService struct {
|
||||
}
|
||||
|
||||
// 创建客户
|
||||
func (c *CustomerService) Create(param *models.CustomerCreateParam) int {
|
||||
customer := models.Customer{
|
||||
Name: param.Name,
|
||||
Source: param.Source,
|
||||
Phone: param.Phone,
|
||||
Email: param.Email,
|
||||
Industry: param.Industry,
|
||||
Level: param.Level,
|
||||
Remarks: param.Remarks,
|
||||
Region: param.Region,
|
||||
Address: param.Address,
|
||||
Status: 1,
|
||||
Creator: param.Creator,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
if err := global.Db.Create(&customer).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 更新客户
|
||||
func (c *CustomerService) Update(param *models.CustomerUpdateParam) int {
|
||||
customer := models.Customer{
|
||||
Name: param.Name,
|
||||
Source: param.Source,
|
||||
Phone: param.Phone,
|
||||
Email: param.Email,
|
||||
Industry: param.Industry,
|
||||
Level: param.Level,
|
||||
Remarks: param.Remarks,
|
||||
Region: param.Region,
|
||||
Address: param.Address,
|
||||
Status: param.Status,
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err := global.Db.Model(&models.Customer{}).Where("id = ?", param.Id).Updates(&customer).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 删除客户
|
||||
func (c *CustomerService) Delete(param *models.CustomerDeleteParam) int {
|
||||
if err := global.Db.Delete(&models.Customer{}, param.Ids).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询客户列表
|
||||
func (c *CustomerService) QueryList(param *models.CustomerQueryParam) ([]*models.CustomerList, int64, int) {
|
||||
customer := models.Customer{
|
||||
Name: param.Name,
|
||||
Creator: param.Creator,
|
||||
}
|
||||
customerList := make([]*models.CustomerList, 0)
|
||||
rows, err := restPage(param.Page, CUSTOMER, customer, &customerList, &[]*models.CustomerList{})
|
||||
if err != nil {
|
||||
return nil, 0, response.ErrCodeFailed
|
||||
}
|
||||
return customerList, rows, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询客户信息
|
||||
func (c *CustomerService) QueryInfo(param *models.CustomerQueryParam) (*models.CustomerInfo, int) {
|
||||
customer := models.Customer{
|
||||
Id: param.Id,
|
||||
}
|
||||
customerInfo := models.CustomerInfo{}
|
||||
err := global.Db.Table(CUSTOMER).Where(&customer).First(&customerInfo).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return &customerInfo, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询客户选项
|
||||
func (c *CustomerService) QueryOption(uid int64) ([]*models.CustomerOption, int) {
|
||||
customer := models.Customer{
|
||||
Creator: uid,
|
||||
}
|
||||
option := make([]*models.CustomerOption, 0)
|
||||
err := global.Db.Table(CUSTOMER).Where(&customer).Find(&option).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return option, response.ErrCodeSuccess
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DashboardService struct {
|
||||
}
|
||||
|
||||
// 数据汇总
|
||||
func (d *DashboardService) Summary(uid int64) models.DashboardSum {
|
||||
var ds models.DashboardSum
|
||||
global.Db.Raw("select count(*) from customer where creator = ?", uid).Scan(&ds.Customers)
|
||||
global.Db.Raw("select count(*) from contract where creator = ?", uid).Scan(&ds.Contracts)
|
||||
global.Db.Raw("select sum(amount) from contract where creator = ?", uid).Scan(&ds.ContractAmount)
|
||||
global.Db.Raw("select count(*) from product where creator = ?", uid).Scan(&ds.Products)
|
||||
|
||||
now := time.Now().Unix()
|
||||
con := "created > ? and created < ? and status = 1 and creator = ?"
|
||||
for i, d := 0, 7; i < 7; i++ {
|
||||
day := now - (int64(d) * 24 * 60 * 60)
|
||||
start, end := dayRange(day)
|
||||
fmt.Println(start, end)
|
||||
global.Db.Table(CONTRACT).Where(con, start, end, uid).Pluck("amount", &ds.Amount[i])
|
||||
ds.Date[i] = time.Unix(day, 0).Format("01-02")
|
||||
d--
|
||||
}
|
||||
return ds
|
||||
}
|
||||
|
||||
// 获取某一天的时间范围
|
||||
func dayRange(day int64) (int64, int64) {
|
||||
t := time.Unix(day, 0)
|
||||
start := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
|
||||
end := start.AddDate(0, 0, 1)
|
||||
return start.Unix(), end.Unix()
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
"crm/response"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProductService struct {
|
||||
}
|
||||
|
||||
// 创建产品
|
||||
func (p *ProductService) Create(param *models.ProductCreateParam) int {
|
||||
product := models.Product{
|
||||
Name: param.Name,
|
||||
Type: param.Type,
|
||||
Unit: param.Unit,
|
||||
Code: param.Code,
|
||||
Price: param.Price,
|
||||
Description: param.Description,
|
||||
Status: param.Status,
|
||||
Creator: param.Creator,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
if err := global.Db.Create(&product).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 更新产品
|
||||
func (p *ProductService) Update(param *models.ProductUpdateParam) int {
|
||||
product := models.Product{
|
||||
Id: param.Id,
|
||||
Name: param.Name,
|
||||
Type: param.Type,
|
||||
Unit: param.Unit,
|
||||
Code: param.Code,
|
||||
Price: param.Price,
|
||||
Description: param.Description,
|
||||
Status: param.Status,
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err := global.Db.Model(&product).Updates(&product).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 删除产品
|
||||
func (p *ProductService) Delete(param *models.ProductDeleteParam) int {
|
||||
err := global.Db.Delete(&models.Product{}, param.Ids).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询产品列表
|
||||
func (p *ProductService) QueryList(param *models.ProductQueryParam) ([]*models.ProductList, int64, int) {
|
||||
product := models.Product{
|
||||
Name: param.Name,
|
||||
Status: param.Status,
|
||||
Creator: param.Creator,
|
||||
}
|
||||
productList := make([]*models.ProductList, 0)
|
||||
rows, err := restPage(param.Page, PRODUCT, product, &productList, &[]*models.ProductList{})
|
||||
if err != nil {
|
||||
return nil, 0, response.ErrCodeFailed
|
||||
}
|
||||
return productList, rows, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 查询产品信息
|
||||
func (p *ProductService) QueryInfo(param *models.ProductQueryParam) (*models.ProductInfo, int) {
|
||||
product := models.Product{
|
||||
Id: param.Id,
|
||||
}
|
||||
productInfo := models.ProductInfo{}
|
||||
err := global.Db.Table(PRODUCT).Where(&product).First(&productInfo).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return &productInfo, response.ErrCodeSuccess
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"crm/common"
|
||||
"crm/global"
|
||||
"crm/models"
|
||||
"crm/response"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
const (
|
||||
TOKEN_MAX_EXPIRE_TIME = 7 * 24 // Token最长有效期
|
||||
)
|
||||
|
||||
type UserService struct {
|
||||
}
|
||||
|
||||
// 用户注册
|
||||
func (u *UserService) Register(param *models.UserCreateParam) int {
|
||||
|
||||
// 判断用户是否存在
|
||||
var user = models.User{}
|
||||
err := global.Db.Where("email = ?", param.Email).First(&user).Error
|
||||
if err == nil && user.Id > 0 {
|
||||
return response.ErrCodeUserHasExist
|
||||
}
|
||||
|
||||
// 校验验证码是否正确
|
||||
key := fmt.Sprintf("user:%s:code", param.Email)
|
||||
code := global.Rdb.Get(ctx, key).Val()
|
||||
if code != param.Code {
|
||||
return response.ErrCodeVerityCodeInvalid
|
||||
}
|
||||
|
||||
// 对密码进行加密
|
||||
password, err := bcrypt.GenerateFromPassword([]byte(param.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
newUser := models.User{
|
||||
Email: param.Email,
|
||||
Password: string(password),
|
||||
Version: 1,
|
||||
Status: 1,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
if err := global.Db.Create(&newUser).Error; err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
func (u *UserService) Login(param *models.UserLoginParam) (*models.UserInfo, int) {
|
||||
|
||||
// 判断用户是否存在
|
||||
var user = models.User{}
|
||||
err := global.Db.Where("email = ?", param.Email).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeUserNotExist
|
||||
}
|
||||
|
||||
// 校验账号密码
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(param.Password))
|
||||
if err != nil {
|
||||
return nil, response.ErrCOdeUserEmailOrPass
|
||||
}
|
||||
|
||||
// 生成并保存Token
|
||||
token, err := common.GenToken(user.Id, TOKEN_MAX_EXPIRE_TIME)
|
||||
if err != nil {
|
||||
log.Printf("[error]Login:GenerateToken:%s", err)
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
expiration := time.Duration(TOKEN_MAX_EXPIRE_TIME) * time.Hour
|
||||
if err := global.Rdb.SetEx(ctx, token, "", expiration).Err(); err != nil {
|
||||
log.Printf("[error]Login:SaveToken:%s", err)
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
|
||||
userInfo := models.UserInfo{
|
||||
Uid: user.Id,
|
||||
Token: token,
|
||||
}
|
||||
|
||||
return &userInfo, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
func (u *UserService) GetVerifyCode(email string) int {
|
||||
// 生成6位随机数
|
||||
code := common.RandInt(100000, 999998)
|
||||
|
||||
// 保存验证码
|
||||
key := fmt.Sprintf("user:%s:code", email)
|
||||
if err := global.Rdb.SetEx(ctx, key, strconv.Itoa(code), 10*time.Minute).Err(); err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
content := fmt.Sprintf("验证码%v,您正在找回密码,切勿向他人泄露。", code)
|
||||
err := common.SendMail(email, content)
|
||||
if err != nil {
|
||||
return response.ErrCodeVerityCodeSendFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 忘记密码
|
||||
func (u *UserService) ForgotPass(param *models.UserPassParam) int {
|
||||
// 判断用户是否存在
|
||||
var user = models.User{}
|
||||
if err := global.Db.Where("email = ?", param.Email).First(&user).Error; err != nil {
|
||||
return response.ErrCodeUserNotExist
|
||||
}
|
||||
|
||||
// 校验验证码是否正确
|
||||
key := fmt.Sprintf("user:%s:code", param.Email)
|
||||
code := global.Rdb.Get(ctx, key).Val()
|
||||
if code != param.Code {
|
||||
return response.ErrCodeVerityCodeInvalid
|
||||
}
|
||||
|
||||
// 对密码进行加密,更新密码
|
||||
password, err := bcrypt.GenerateFromPassword([]byte(param.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
upass := models.User{
|
||||
Password: string(password),
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err = global.Db.Model(&models.User{}).Where("email = ?", param.Email).Updates(&upass).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeUserPassResetFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 修改邮箱
|
||||
func (u *UserService) UpdateMail(param *models.UserMailParam) int {
|
||||
// 校验验证码是否正确
|
||||
key := fmt.Sprintf("user:%s:code", param.Email)
|
||||
code := global.Rdb.Get(ctx, key).Val()
|
||||
if code != param.Code {
|
||||
return response.ErrCodeVerityCodeInvalid
|
||||
}
|
||||
user := models.User{
|
||||
Email: param.NewEmail,
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err := global.Db.Table(USER).Where("email = ?", param.Email).Updates(&user).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
func (u *UserService) Logout(token string) int {
|
||||
err := global.Rdb.Del(ctx, token).Err()
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 注销账号
|
||||
func (u *UserService) Delete(param models.UserDeleteParam) int {
|
||||
// 校验验证码是否正确
|
||||
key := fmt.Sprintf("user:%s:code", param.Email)
|
||||
code := global.Rdb.Get(ctx, key).Val()
|
||||
if code != param.Code {
|
||||
return response.ErrCodeVerityCodeInvalid
|
||||
}
|
||||
err := global.Db.Delete(&models.User{}, param.Id).Error
|
||||
if err != nil {
|
||||
return response.ErrCodeFailed
|
||||
}
|
||||
return response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
func (u *UserService) GetInfo(uid int64) (*models.UserPersonInfo, int) {
|
||||
var user models.UserPersonInfo
|
||||
err := global.Db.Table(USER).Where("id = ?", uid).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
|
||||
// 判断用户订阅是否过期
|
||||
if user.Version == 2 && time.Now().Unix() > int64(user.Expired) {
|
||||
err := global.Db.Model(&models.User{}).Where("id = ?", uid).Update("version", 1).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return &user, response.ErrCodeSuccess
|
||||
}
|
||||
return &user, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 订阅个人版
|
||||
func (u *UserService) Buy(uid int64) (*models.UserVerisonInfo, int) {
|
||||
// 订阅一个月按30天计算
|
||||
month := time.Now().Unix() + int64(2592000)
|
||||
user := models.User{
|
||||
Version: 2,
|
||||
Expired: month,
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
err := global.Db.Model(&models.User{}).Where("id = ?", uid).Updates(&user).Error
|
||||
if err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
// 查询版本信息
|
||||
var version models.UserVerisonInfo
|
||||
if err := global.Db.Table(USER).Where("id = ?", uid).First(&version).Error; err != nil {
|
||||
return nil, response.ErrCodeFailed
|
||||
}
|
||||
return &version, response.ErrCodeSuccess
|
||||
}
|
||||
|
||||
// 校验用户Token
|
||||
func (u *UserService) VerifyToken(token string) error {
|
||||
return global.Rdb.Exists(ctx, token).Err()
|
||||
}
|
||||
Reference in New Issue
Block a user