mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-20 20:59:16 +00:00
feat: added user association to queues
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
secret: process.env.JWT_SECRET || "mysecret",
|
secret: process.env.JWT_SECRET || "mysecret",
|
||||||
expiresIn: "15m",
|
expiresIn: "15d",
|
||||||
refreshSecret: process.env.JWT_REFRESH_SECRET || "myanothersecret",
|
refreshSecret: process.env.JWT_REFRESH_SECRET || "myanothersecret",
|
||||||
refreshExpiresIn: "7d"
|
refreshExpiresIn: "7d"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { email, password, name, profile } = req.body;
|
const { email, password, name, profile, queueIds } = req.body;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
req.url === "/signup" &&
|
req.url === "/signup" &&
|
||||||
@@ -42,7 +42,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
name,
|
name,
|
||||||
profile
|
profile,
|
||||||
|
queueIds
|
||||||
});
|
});
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import ContactCustomField from "../models/ContactCustomField";
|
|||||||
import Message from "../models/Message";
|
import Message from "../models/Message";
|
||||||
import Queue from "../models/Queue";
|
import Queue from "../models/Queue";
|
||||||
import WhatsappQueue from "../models/WhatsappQueue";
|
import WhatsappQueue from "../models/WhatsappQueue";
|
||||||
|
import UserQueue from "../models/UserQueue";
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const dbConfig = require("../config/database");
|
const dbConfig = require("../config/database");
|
||||||
@@ -24,7 +25,8 @@ const models = [
|
|||||||
ContactCustomField,
|
ContactCustomField,
|
||||||
Setting,
|
Setting,
|
||||||
Queue,
|
Queue,
|
||||||
WhatsappQueue
|
WhatsappQueue,
|
||||||
|
UserQueue
|
||||||
];
|
];
|
||||||
|
|
||||||
sequelize.addModels(models);
|
sequelize.addModels(models);
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { QueryInterface, DataTypes } from "sequelize";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.createTable("UserQueues", {
|
||||||
|
userId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
primaryKey: true
|
||||||
|
},
|
||||||
|
queueId: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
primaryKey: true
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.dropTable("UserQueues");
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -10,6 +10,8 @@ import {
|
|||||||
Unique,
|
Unique,
|
||||||
BelongsToMany
|
BelongsToMany
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
|
import User from "./User";
|
||||||
|
import UserQueue from "./UserQueue";
|
||||||
|
|
||||||
import Whatsapp from "./Whatsapp";
|
import Whatsapp from "./Whatsapp";
|
||||||
import WhatsappQueue from "./WhatsappQueue";
|
import WhatsappQueue from "./WhatsappQueue";
|
||||||
@@ -39,6 +41,9 @@ class Queue extends Model<Queue> {
|
|||||||
|
|
||||||
@BelongsToMany(() => Whatsapp, () => WhatsappQueue)
|
@BelongsToMany(() => Whatsapp, () => WhatsappQueue)
|
||||||
whatsapps: Array<Whatsapp & { WhatsappQueue: WhatsappQueue }>;
|
whatsapps: Array<Whatsapp & { WhatsappQueue: WhatsappQueue }>;
|
||||||
|
|
||||||
|
@BelongsToMany(() => User, () => UserQueue)
|
||||||
|
users: Array<User & { UserQueue: UserQueue }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Queue;
|
export default Queue;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
|
|
||||||
import Contact from "./Contact";
|
import Contact from "./Contact";
|
||||||
import Message from "./Message";
|
import Message from "./Message";
|
||||||
|
import Queue from "./Queue";
|
||||||
import User from "./User";
|
import User from "./User";
|
||||||
import Whatsapp from "./Whatsapp";
|
import Whatsapp from "./Whatsapp";
|
||||||
|
|
||||||
@@ -64,6 +65,13 @@ class Ticket extends Model<Ticket> {
|
|||||||
@BelongsTo(() => Whatsapp)
|
@BelongsTo(() => Whatsapp)
|
||||||
whatsapp: Whatsapp;
|
whatsapp: Whatsapp;
|
||||||
|
|
||||||
|
@ForeignKey(() => Queue)
|
||||||
|
@Column
|
||||||
|
queueId: number;
|
||||||
|
|
||||||
|
@BelongsTo(() => Queue)
|
||||||
|
queue: Queue;
|
||||||
|
|
||||||
@HasMany(() => Message)
|
@HasMany(() => Message)
|
||||||
messages: Message[];
|
messages: Message[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import {
|
|||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
AutoIncrement,
|
AutoIncrement,
|
||||||
Default,
|
Default,
|
||||||
HasMany
|
HasMany,
|
||||||
|
BelongsToMany
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
import { hash, compare } from "bcryptjs";
|
import { hash, compare } from "bcryptjs";
|
||||||
import Ticket from "./Ticket";
|
import Ticket from "./Ticket";
|
||||||
|
import Queue from "./Queue";
|
||||||
|
import UserQueue from "./UserQueue";
|
||||||
|
|
||||||
@Table
|
@Table
|
||||||
class User extends Model<User> {
|
class User extends Model<User> {
|
||||||
@@ -51,6 +54,9 @@ class User extends Model<User> {
|
|||||||
@HasMany(() => Ticket)
|
@HasMany(() => Ticket)
|
||||||
tickets: Ticket[];
|
tickets: Ticket[];
|
||||||
|
|
||||||
|
@BelongsToMany(() => Queue, () => UserQueue)
|
||||||
|
queues: Queue[];
|
||||||
|
|
||||||
@BeforeUpdate
|
@BeforeUpdate
|
||||||
@BeforeCreate
|
@BeforeCreate
|
||||||
static hashPassword = async (instance: User): Promise<void> => {
|
static hashPassword = async (instance: User): Promise<void> => {
|
||||||
|
|||||||
29
backend/src/models/UserQueue.ts
Normal file
29
backend/src/models/UserQueue.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import {
|
||||||
|
Table,
|
||||||
|
Column,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
Model,
|
||||||
|
ForeignKey
|
||||||
|
} from "sequelize-typescript";
|
||||||
|
import Queue from "./Queue";
|
||||||
|
import User from "./User";
|
||||||
|
|
||||||
|
@Table
|
||||||
|
class UserQueue extends Model<UserQueue> {
|
||||||
|
@ForeignKey(() => User)
|
||||||
|
@Column
|
||||||
|
userId: number;
|
||||||
|
|
||||||
|
@ForeignKey(() => Queue)
|
||||||
|
@Column
|
||||||
|
queueId: number;
|
||||||
|
|
||||||
|
@CreatedAt
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@UpdatedAt
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserQueue;
|
||||||
@@ -7,6 +7,7 @@ interface Request {
|
|||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
queueIds?: number[];
|
||||||
profile?: string;
|
profile?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ const CreateUserService = async ({
|
|||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
name,
|
name,
|
||||||
|
queueIds = [],
|
||||||
profile = "admin"
|
profile = "admin"
|
||||||
}: Request): Promise<Response> => {
|
}: Request): Promise<Response> => {
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
@@ -47,18 +49,26 @@ const CreateUserService = async ({
|
|||||||
throw new AppError(err.message);
|
throw new AppError(err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await User.create({
|
const user = await User.create(
|
||||||
|
{
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
name,
|
name,
|
||||||
profile
|
profile
|
||||||
});
|
},
|
||||||
|
{ include: ["queues"] }
|
||||||
|
);
|
||||||
|
|
||||||
|
await user.$set("queues", queueIds);
|
||||||
|
|
||||||
|
await user.reload();
|
||||||
|
|
||||||
const serializedUser = {
|
const serializedUser = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
profile: user.profile
|
profile: user.profile,
|
||||||
|
queues: user.queues
|
||||||
};
|
};
|
||||||
|
|
||||||
return serializedUser;
|
return serializedUser;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Sequelize, Op } from "sequelize";
|
import { Sequelize, Op } from "sequelize";
|
||||||
|
import Queue from "../../models/Queue";
|
||||||
import User from "../../models/User";
|
import User from "../../models/User";
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
@@ -19,8 +20,8 @@ const ListUsersService = async ({
|
|||||||
const whereCondition = {
|
const whereCondition = {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{
|
{
|
||||||
name: Sequelize.where(
|
"$User.name$": Sequelize.where(
|
||||||
Sequelize.fn("LOWER", Sequelize.col("name")),
|
Sequelize.fn("LOWER", Sequelize.col("User.name")),
|
||||||
"LIKE",
|
"LIKE",
|
||||||
`%${searchParam.toLowerCase()}%`
|
`%${searchParam.toLowerCase()}%`
|
||||||
)
|
)
|
||||||
@@ -33,10 +34,13 @@ const ListUsersService = async ({
|
|||||||
|
|
||||||
const { count, rows: users } = await User.findAndCountAll({
|
const { count, rows: users } = await User.findAndCountAll({
|
||||||
where: whereCondition,
|
where: whereCondition,
|
||||||
attributes: ["name", "id", "email", "profile"],
|
attributes: ["name", "id", "email", "profile", "createdAt"],
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
order: [["createdAt", "DESC"]]
|
order: [["createdAt", "DESC"]],
|
||||||
|
include: [
|
||||||
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasMore = count > offset + users.length;
|
const hasMore = count > offset + users.length;
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import User from "../../models/User";
|
import User from "../../models/User";
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
|
import Queue from "../../models/Queue";
|
||||||
|
|
||||||
const ShowUserService = async (id: string | number): Promise<User> => {
|
const ShowUserService = async (id: string | number): Promise<User> => {
|
||||||
const user = await User.findByPk(id, {
|
const user = await User.findByPk(id, {
|
||||||
attributes: ["name", "id", "email", "profile", "tokenVersion"]
|
attributes: ["name", "id", "email", "profile", "tokenVersion"],
|
||||||
|
include: [
|
||||||
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
import User from "../../models/User";
|
import ShowUserService from "./ShowUserService";
|
||||||
|
|
||||||
interface UserData {
|
interface UserData {
|
||||||
email?: string;
|
email?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
|
queueIds?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
@@ -26,14 +27,7 @@ const UpdateUserService = async ({
|
|||||||
userData,
|
userData,
|
||||||
userId
|
userId
|
||||||
}: Request): Promise<Response | undefined> => {
|
}: Request): Promise<Response | undefined> => {
|
||||||
const user = await User.findOne({
|
const user = await ShowUserService(userId);
|
||||||
where: { id: userId },
|
|
||||||
attributes: ["name", "id", "email", "profile"]
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
throw new AppError("ERR_NO_USER_FOUND", 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
name: Yup.string().min(2),
|
name: Yup.string().min(2),
|
||||||
@@ -42,7 +36,7 @@ const UpdateUserService = async ({
|
|||||||
password: Yup.string()
|
password: Yup.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
const { email, password, profile, name } = userData;
|
const { email, password, profile, name, queueIds = [] } = userData;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await schema.validate({ email, password, profile, name });
|
await schema.validate({ email, password, profile, name });
|
||||||
@@ -57,11 +51,16 @@ const UpdateUserService = async ({
|
|||||||
name
|
name
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await user.$set("queues", queueIds);
|
||||||
|
|
||||||
|
await user.reload();
|
||||||
|
|
||||||
const serializedUser = {
|
const serializedUser = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
profile: user.profile
|
profile: user.profile,
|
||||||
|
queues: user.queues
|
||||||
};
|
};
|
||||||
|
|
||||||
return serializedUser;
|
return serializedUser;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface Response {
|
|||||||
const CreateWhatsAppService = async ({
|
const CreateWhatsAppService = async ({
|
||||||
name,
|
name,
|
||||||
status = "OPENING",
|
status = "OPENING",
|
||||||
queueIds,
|
queueIds = [],
|
||||||
isDefault = false
|
isDefault = false
|
||||||
}: Request): Promise<Response> => {
|
}: Request): Promise<Response> => {
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
@@ -64,14 +64,19 @@ const CreateWhatsAppService = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const whatsapp = await Whatsapp.create({
|
const whatsapp = await Whatsapp.create(
|
||||||
|
{
|
||||||
name,
|
name,
|
||||||
status,
|
status,
|
||||||
isDefault
|
isDefault
|
||||||
});
|
},
|
||||||
|
{ include: ["queues"] }
|
||||||
|
);
|
||||||
|
|
||||||
await whatsapp.$set("queues", queueIds);
|
await whatsapp.$set("queues", queueIds);
|
||||||
|
|
||||||
|
await whatsapp.reload();
|
||||||
|
|
||||||
return { whatsapp, oldDefaultWhatsapp };
|
return { whatsapp, oldDefaultWhatsapp };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import Whatsapp from "../../models/Whatsapp";
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
|
import Queue from "../../models/Queue";
|
||||||
|
|
||||||
const ShowWhatsAppService = async (id: string | number): Promise<Whatsapp> => {
|
const ShowWhatsAppService = async (id: string | number): Promise<Whatsapp> => {
|
||||||
const whatsapp = await Whatsapp.findByPk(id);
|
const whatsapp = await Whatsapp.findByPk(id, {
|
||||||
|
include: [
|
||||||
|
{ model: Queue, as: "queues", attributes: ["id", "name", "color"] }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
if (!whatsapp) {
|
if (!whatsapp) {
|
||||||
throw new AppError("ERR_NO_WAPP_FOUND", 404);
|
throw new AppError("ERR_NO_WAPP_FOUND", 404);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Op } from "sequelize";
|
|||||||
|
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
import Whatsapp from "../../models/Whatsapp";
|
import Whatsapp from "../../models/Whatsapp";
|
||||||
|
import ShowWhatsAppService from "./ShowWhatsAppService";
|
||||||
|
|
||||||
interface WhatsappData {
|
interface WhatsappData {
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -50,13 +51,8 @@ const UpdateWhatsAppService = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const whatsapp = await Whatsapp.findOne({
|
const whatsapp = await ShowWhatsAppService(whatsappId);
|
||||||
where: { id: whatsappId }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!whatsapp) {
|
|
||||||
throw new AppError("ERR_NO_WAPP_FOUND", 404);
|
|
||||||
}
|
|
||||||
await whatsapp.update({
|
await whatsapp.update({
|
||||||
name,
|
name,
|
||||||
status,
|
status,
|
||||||
@@ -66,6 +62,8 @@ const UpdateWhatsAppService = async ({
|
|||||||
|
|
||||||
await whatsapp.$set("queues", queueIds);
|
await whatsapp.$set("queues", queueIds);
|
||||||
|
|
||||||
|
await whatsapp.reload();
|
||||||
|
|
||||||
return { whatsapp, oldDefaultWhatsapp };
|
return { whatsapp, oldDefaultWhatsapp };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user