Remove backend files #98
@ -1,74 +0,0 @@
 | 
				
			|||||||
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
 | 
					 | 
				
			||||||
@ -1,3 +0,0 @@
 | 
				
			|||||||
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,44 +0,0 @@
 | 
				
			|||||||
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);
 | 
					 | 
				
			||||||
@ -1,24 +0,0 @@
 | 
				
			|||||||
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);
 | 
					 | 
				
			||||||
@ -1,83 +0,0 @@
 | 
				
			|||||||
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);
 | 
					 | 
				
			||||||
@ -1,149 +0,0 @@
 | 
				
			|||||||
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
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user