dogsitters-finder #91
No files matched your search
@@ -0,0 +1,74 @@
|
|||||||
|
const { Router } = require("express");
|
||||||
|
const hash = require("pbkdf2-password")();
|
||||||
|
const { promisify } = require("node:util");
|
||||||
|
const jwt = require('jsonwebtoken')
|
||||||
|
|
||||||
|
const { getAnswer } = require("../../utils/common");
|
||||||
|
|
||||||
|
const { AuthModel } = require("./model/todo/auth");
|
||||||
|
const { TOKEN_KEY } = require('./const')
|
||||||
|
const { UserModel } = require("./model/todo/user");
|
||||||
|
|
||||||
|
const { requiredValidate } = require('./utils')
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
"/signup",
|
||||||
|
requiredValidate("login", "password", "email"),
|
||||||
|
async (req, res, next) => {
|
||||||
|
const { login, password, email } = req.body
|
||||||
|
|
||||||
|
const user = await AuthModel.findOne({ login });
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
throw new Error("Пользователь с таким логином уже существует");
|
||||||
|
}
|
||||||
|
|
||||||
|
hash({ password }, async function (err, pass, salt, hash) {
|
||||||
|
if (err) return next(err);
|
||||||
|
|
||||||
|
const user = await UserModel.create({ login, email });
|
||||||
|
await AuthModel.create({ login, hash, salt, userId: user.id });
|
||||||
|
|
||||||
|
res.json(getAnswer(null, { ok: true }))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function authenticate(login, pass, cb) {
|
||||||
|
AuthModel.findOne({ login }).populate('userId').exec().then((user) => {
|
||||||
|
if (!user) return cb(null, null)
|
||||||
|
|
||||||
|
hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
if (hash === user.hash) return cb(null, user)
|
||||||
|
cb(null, null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth = promisify(authenticate)
|
||||||
|
|
||||||
|
router.post('/signin', requiredValidate('login', 'password'), async (req, res) => {
|
||||||
|
const { login, password } = req.body
|
||||||
|
|
||||||
|
const user = await auth(login, password)
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("Неверный логин или пароль")
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessToken = jwt.sign({
|
||||||
|
...JSON.parse(JSON.stringify(user.userId)),
|
||||||
|
}, TOKEN_KEY, {
|
||||||
|
expiresIn: '12h'
|
||||||
|
})
|
||||||
|
|
||||||
|
res.json(getAnswer(null, {
|
||||||
|
user: user.userId,
|
||||||
|
token: accessToken,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
exports.DSF_AUTH_PASSWD_MODEL_NAME = 'DSF_AUTH_PASSWD'
|
||||||
|
exports.DSF_AUTH_USER_MODEL_NAME = 'DSF_AUTH_USER'
|
||||||
|
exports.DSF_INTERACTION_MODEL_NAME = 'DSF_INTERACTION'
|
||||||
@@ -1,40 +1,52 @@
|
|||||||
const router = require("express").Router();
|
// const router = require("express").Router();
|
||||||
|
|
||||||
router.get("/users", (request, response) => {
|
// router.get("/users", (request, response) => {
|
||||||
response.send(require("./json/users/users.json"));
|
// response.send(require("./json/users/users.json"));
|
||||||
});
|
// });
|
||||||
|
|
||||||
router.post("/auth", (request, response) => {
|
// router.post("/auth", (request, response) => {
|
||||||
const { phoneNumber, password } = request.body;
|
// const { phoneNumber, password } = request.body;
|
||||||
console.log(phoneNumber, password);
|
// console.log(phoneNumber, password);
|
||||||
if (phoneNumber === "89999999999") {
|
// if (phoneNumber === "89999999999") {
|
||||||
response.send(require("./json/auth/dogsitter.success.json"));
|
// response.send(require("./json/auth/dogsitter.success.json"));
|
||||||
} else if (phoneNumber === "89555555555") {
|
// } else if (phoneNumber === "89555555555") {
|
||||||
response.status(400).send(require("./json/auth/error.json"));
|
// response.status(400).send(require("./json/auth/error.json"));
|
||||||
} else {
|
// } else {
|
||||||
response.send(require("./json/auth/owner.success.json"));
|
// response.send(require("./json/auth/owner.success.json"));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
router.post("/auth/2fa", (request, response) => {
|
// router.post("/auth/2fa", (request, response) => {
|
||||||
const { code } = request.body;
|
// const { code } = request.body;
|
||||||
if (code === "0000") {
|
// if (code === "0000") {
|
||||||
response.send(require("./json/2fa/success.json"));
|
// response.send(require("./json/2fa/success.json"));
|
||||||
} else {
|
// } else {
|
||||||
response.status(400).send(require("./json/2fa/error.json"));
|
// response.status(400).send(require("./json/2fa/error.json"));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
router.post("/register", (request, response) => {
|
// router.post("/register", (request, response) => {
|
||||||
const { firstName, secondName, phoneNumber, password, role } = request.body;
|
// const { firstName, secondName, phoneNumber, password, role } = request.body;
|
||||||
console.log(phoneNumber, password, role);
|
// console.log(phoneNumber, password, role);
|
||||||
if (phoneNumber === "89283244141" || phoneNumber === "89872855893") {
|
// if (phoneNumber === "89283244141" || phoneNumber === "89872855893") {
|
||||||
response.status(400).send(require("./json/register/error.json"));
|
// response.status(400).send(require("./json/register/error.json"));
|
||||||
} else if (role === "dogsitter") {
|
// } else if (role === "dogsitter") {
|
||||||
response.send(require("./json/register/dogsitter.success.json"));
|
// response.send(require("./json/register/dogsitter.success.json"));
|
||||||
} else {
|
// } else {
|
||||||
response.send(require("./json/register/owner.success.json"));
|
// response.send(require("./json/register/owner.success.json"));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
module.exports = router;
|
// module.exports = router;
|
||||||
|
|
||||||
|
const { Router } = require('express')
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
const userInteractionRouter = require('./routes')
|
||||||
|
const authRouter = require('./auth')
|
||||||
|
|
||||||
|
router.use('/auth', authRouter)
|
||||||
|
router.use('/user-interaction', userInteractionRouter)
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,44 @@
|
|||||||
|
const { Schema, model } = require("mongoose");
|
||||||
|
|
||||||
|
const {
|
||||||
|
DSF_AUTH_PASSWD_MODEL_NAME,
|
||||||
|
DSF_AUTH_USER_MODEL_NAME,
|
||||||
|
} = require("../../const");
|
||||||
|
|
||||||
|
const schema = new Schema({
|
||||||
|
login: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
hash: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
salt: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
userId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: DSF_AUTH_USER_MODEL_NAME
|
||||||
|
},
|
||||||
|
created: {
|
||||||
|
type: Date,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
schema.set("toJSON", {
|
||||||
|
virtuals: true,
|
||||||
|
versionKey: false,
|
||||||
|
transform: function (doc, ret) {
|
||||||
|
delete ret._id;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
schema.virtual("id").get(function () {
|
||||||
|
return this._id.toHexString();
|
||||||
|
});
|
||||||
|
|
||||||
|
exports.AuthModel = model(DSF_AUTH_PASSWD_MODEL_NAME, schema);
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const { Schema, model } = require("mongoose");
|
||||||
|
|
||||||
|
const { DSF_AUTH_USER_MODEL_NAME, DSF_INTERACTION_MODEL_NAME } = require("../../const");
|
||||||
|
|
||||||
|
const interactionSchema = new Schema({
|
||||||
|
owner_id: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: DSF_AUTH_USER_MODEL_NAME,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
dogsitter_id: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: DSF_AUTH_USER_MODEL_NAME,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
interactionSchema.index({ owner_id: 1, dogsitter_id: 1 });
|
||||||
|
|
||||||
|
module.exports.Interaction = model(DSF_INTERACTION_MODEL_NAME, interactionSchema);
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
const { Schema, model } = require("mongoose");
|
||||||
|
|
||||||
|
const { DSF_AUTH_USER_MODEL_NAME } = require("../../const");
|
||||||
|
|
||||||
|
const userSchema = new Schema({
|
||||||
|
phone_number: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
match: /^\+?\d{10,15}$/
|
||||||
|
},
|
||||||
|
first_name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
second_name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
type: String,
|
||||||
|
enum: ["dogsitter", "owner"],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
type: String,
|
||||||
|
required: function() {
|
||||||
|
return this.role === "dogsitter";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
min: 0,
|
||||||
|
required: function() {
|
||||||
|
return this.role === "dogsitter";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
about_me: {
|
||||||
|
type: String,
|
||||||
|
maxlength: 500
|
||||||
|
},
|
||||||
|
rating: {
|
||||||
|
type: Number,
|
||||||
|
min: 0,
|
||||||
|
max: 5,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
ratings: {
|
||||||
|
type: [Number],
|
||||||
|
default: [],
|
||||||
|
validate: {
|
||||||
|
validator: function(arr) {
|
||||||
|
return arr.every(v => v >= 0 && v <= 5);
|
||||||
|
},
|
||||||
|
message: "Рейтинг должен быть в диапазоне от 0 до 5!"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tg: {
|
||||||
|
type: String,
|
||||||
|
match: /^[a-zA-Z0-9_]{5,32}$/
|
||||||
|
},
|
||||||
|
created: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
userSchema.virtual("id").get(function() {
|
||||||
|
return this._id.toHexString();
|
||||||
|
});
|
||||||
|
|
||||||
|
userSchema.set("toJSON", {
|
||||||
|
virtuals: true,
|
||||||
|
versionKey: false,
|
||||||
|
transform: function(doc, ret) {
|
||||||
|
delete ret._id;
|
||||||
|
delete ret.__v;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.User = model(DSF_AUTH_USER_MODEL_NAME, userSchema);
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
const { Router } = require('express')
|
||||||
|
const { expressjwt } = require('express-jwt')
|
||||||
|
|
||||||
|
const { getAnswer } = require('../../utils/common')
|
||||||
|
const { User, Interaction } = require('./model')
|
||||||
|
const { TOKEN_KEY } = require('./const')
|
||||||
|
const { requiredValidate } = require('./utils')
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
// Получение списка пользователей
|
||||||
|
router.get('/users', async (req, res) => {
|
||||||
|
|
||||||
|
const users = await User.find()
|
||||||
|
.select('-__v -ratings -phone_number')
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
console.log('get users successfull')
|
||||||
|
|
||||||
|
res.send(getAnswer(null, users))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Получение конкретного пользователя
|
||||||
|
router.get('/dogsitter-viewing', async (req, res) => {
|
||||||
|
const { userId } = req.params
|
||||||
|
|
||||||
|
const user = await User.findById(userId)
|
||||||
|
.select('-__v -ratings')
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).send(getAnswer(new Error('Пользователь не найден')))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send(getAnswer(null, user))
|
||||||
|
})
|
||||||
|
|
||||||
|
router.use(expressjwt({ secret: TOKEN_KEY, algorithms: ['HS256'] }))
|
||||||
|
|
||||||
|
// Добавление оценки пользователю
|
||||||
|
router.post('/dogsitter-viewing/rating', requiredValidate('value'), async (req, res) => {
|
||||||
|
const { userId } = req.params
|
||||||
|
const { value } = req.body
|
||||||
|
const authUserId = req.auth.id
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await User.findById(userId)
|
||||||
|
if (!user) throw new Error('Пользователь не найден')
|
||||||
|
if (user.role !== 'dogsitter') throw new Error('Нельзя оценивать этого пользователя')
|
||||||
|
if (user.id === authUserId) throw new Error('Нельзя оценивать самого себя')
|
||||||
|
|
||||||
|
user.ratings.push(Number(value))
|
||||||
|
user.rating = user.ratings.reduce((a, b) => a + b, 0) / user.ratings.length
|
||||||
|
|
||||||
|
const updatedUser = await user.save()
|
||||||
|
|
||||||
|
res.send(getAnswer(null, {
|
||||||
|
id: updatedUser.id,
|
||||||
|
rating: updatedUser.rating.toFixed(1),
|
||||||
|
totalRatings: updatedUser.ratings.length
|
||||||
|
}))
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).send(getAnswer(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Обновление информации пользователя
|
||||||
|
router.patch('/users', async (req, res) => {
|
||||||
|
const { userId } = req.params
|
||||||
|
const updates = req.body
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await User.findByIdAndUpdate(userId, updates, { new: true })
|
||||||
|
.select('-__v -ratings')
|
||||||
|
|
||||||
|
if (!user) throw new Error('Пользователь не найден')
|
||||||
|
res.send(getAnswer(null, user))
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).send(getAnswer(error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Создание объекта взаимодействия
|
||||||
|
router.post('/interactions',
|
||||||
|
expressjwt({ secret: TOKEN_KEY, algorithms: ['HS256'] }),
|
||||||
|
requiredValidate('dogsitter_id'),
|
||||||
|
async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { dogsitter_id } = req.body
|
||||||
|
const owner_id = req.auth.id // ID из JWT токена
|
||||||
|
|
||||||
|
// Проверка существования пользователей
|
||||||
|
const [owner, dogsitter] = await Promise.all([
|
||||||
|
User.findById(owner_id),
|
||||||
|
User.findById(dogsitter_id)
|
||||||
|
])
|
||||||
|
|
||||||
|
if (!owner || owner.role !== 'owner') {
|
||||||
|
throw new Error('Владелец не найден или имеет неверную роль')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dogsitter || dogsitter.role !== 'dogsitter') {
|
||||||
|
throw new Error('Догситтер не найден или имеет неверную роль')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создание взаимодействия
|
||||||
|
const interaction = await Interaction.create({
|
||||||
|
owner_id,
|
||||||
|
dogsitter_id
|
||||||
|
})
|
||||||
|
|
||||||
|
res.send(getAnswer(null, {
|
||||||
|
id: interaction.id,
|
||||||
|
timestamp: interaction.timestamp
|
||||||
|
}))
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
res.status(400).send(getAnswer(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
router.get('/interactions/check', async (req, res) => {
|
||||||
|
const { owner_id, dogsitter_id } = req.query;
|
||||||
|
|
||||||
|
if (!owner_id || !dogsitter_id) {
|
||||||
|
return res.status(400).send(getAnswer('Missing owner_id or dogsitter_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Поиск взаимодействий по owner_id и dogsitter_id
|
||||||
|
const interactions = await Interaction.find({ owner_id, dogsitter_id })
|
||||||
|
.select('-__v') // Выбираем только нужные поля
|
||||||
|
.lean();
|
||||||
|
|
||||||
|
if (interactions.length === 0) {
|
||||||
|
return res.status(404).send(getAnswer('No interactions found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send(getAnswer(null, interactions));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking interactions:', error);
|
||||||
|
res.status(500).send(getAnswer('Internal Server Error'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
Reference in new issue
Block a user