front-end almost done | started back-end
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
const jwt = require('jsonwebtoken');
|
||||
const Admin = require('./models/admin/Admin')
|
||||
const User = require('./models/user/User')
|
||||
|
||||
const config = {
|
||||
// secret for generating jwt token
|
||||
secretKey: '2664debdbef6fdd2ae52ba2c9cd4d1d15f3cdca31a641aacad1a5c43cda91b55a145b3f4c573f69aeba3c942bf55417593ff74f7d192a5664358ee753ea09e8e'
|
||||
}
|
||||
|
||||
module.exports = config
|
||||
|
||||
// check if admin logged in
|
||||
module.exports.isAdmin = function (req, res, next) {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
// check if token is not destroyed
|
||||
Admin.findOne({token: token}, (err, user) => {
|
||||
if (err) throw err
|
||||
if (user) {
|
||||
// verifies secret and checks if the token is expired
|
||||
jwt.verify(user.token.replace(/^Bearer\s/, ''), config.secretKey, (err, decoded) => {
|
||||
if (err) {
|
||||
return res.status(401).json({message: 'unauthorized'})
|
||||
} else {
|
||||
return next()
|
||||
}
|
||||
})
|
||||
} else return res.status(401).json({message: 'unauthorized'})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: 'unauthorized'})
|
||||
}
|
||||
}
|
||||
|
||||
// check if user logged in
|
||||
module.exports.isUser = function (req, res, next) {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
// check if token is not destroyed
|
||||
User.findOne({token: token}, (err, user) => {
|
||||
if (err) throw err
|
||||
if (user) {
|
||||
// verifies secret and checks if the token is expired
|
||||
jwt.verify(user.token.replace(/^Bearer\s/, ''), config.secretKey, (err, decoded) => {
|
||||
if (err) {
|
||||
return res.status(401).json({message: 'unauthorized'})
|
||||
} else {
|
||||
return next()
|
||||
}
|
||||
})
|
||||
} else return res.status(401).json({message: 'unauthorized'})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: 'unauthorized'})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
const AboutPageContent = require('../models/AboutPageContent')
|
||||
const dateformat = require('dateformat')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const jimp = require('jimp')
|
||||
const fs = require('fs')
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
// fa
|
||||
body('fa_page_title')
|
||||
.notEmpty().withMessage('تیتر بالای صفحه نباید خالی باشد.'),
|
||||
body('fa_s1_title')
|
||||
.notEmpty().withMessage('تیتر بخش اول نباید خالی باشد.'),
|
||||
body('fa_s1_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش اول نباید خالی باشد.'),
|
||||
body('fa_s2_title')
|
||||
.notEmpty().withMessage('تیتر بخش دوم نباید خالی باشد.'),
|
||||
body('fa_s2_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش دوم نباید خالی باشد.'),
|
||||
body('fa_s2_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش دوم نباید خالی باشد.'),
|
||||
body('fa_s3_title')
|
||||
.notEmpty().withMessage('تیتر بخش سوم نباید خالی باشد.'),
|
||||
body('fa_s3_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش سوم نباید خالی باشد.'),
|
||||
body('fa_s3_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش سوم نباید خالی باشد.'),
|
||||
body('fa_s4_text')
|
||||
.notEmpty().withMessage('متن بخش چهارم نباید خالی باشد.'),
|
||||
body('fa_last_section_title')
|
||||
.notEmpty().withMessage('تیتر بخش آخر نباید خالی باشد.'),
|
||||
body('fa_last_section_text')
|
||||
.notEmpty().withMessage('متن بخش آخر نباید خالی باشد.'),
|
||||
|
||||
// en
|
||||
body('en_page_title')
|
||||
.notEmpty().withMessage('تیتر بالای صفحه نباید خالی باشد.'),
|
||||
body('en_s1_title')
|
||||
.notEmpty().withMessage('تیتر بخش اول نباید خالی باشد.'),
|
||||
body('en_s1_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش اول نباید خالی باشد.'),
|
||||
body('en_s2_title')
|
||||
.notEmpty().withMessage('تیتر بخش دوم نباید خالی باشد.'),
|
||||
body('en_s2_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش دوم نباید خالی باشد.'),
|
||||
body('en_s2_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش دوم نباید خالی باشد.'),
|
||||
body('en_s3_title')
|
||||
.notEmpty().withMessage('تیتر بخش سوم نباید خالی باشد.'),
|
||||
body('en_s3_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش سوم نباید خالی باشد.'),
|
||||
body('en_s3_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش سوم نباید خالی باشد.'),
|
||||
body('en_s4_text')
|
||||
.notEmpty().withMessage('متن بخش چهارم نباید خالی باشد.'),
|
||||
body('en_last_section_title')
|
||||
.notEmpty().withMessage('تیتر بخش آخر نباید خالی باشد.'),
|
||||
body('en_last_section_text')
|
||||
.notEmpty().withMessage('متن بخش آخر نباید خالی باشد.'),
|
||||
|
||||
// de
|
||||
body('de_page_title')
|
||||
.notEmpty().withMessage('تیتر بالای صفحه نباید خالی باشد.'),
|
||||
body('de_s1_title')
|
||||
.notEmpty().withMessage('تیتر بخش اول نباید خالی باشد.'),
|
||||
body('de_s1_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش اول نباید خالی باشد.'),
|
||||
body('de_s2_title')
|
||||
.notEmpty().withMessage('تیتر بخش دوم نباید خالی باشد.'),
|
||||
body('de_s2_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش دوم نباید خالی باشد.'),
|
||||
body('de_s2_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش دوم نباید خالی باشد.'),
|
||||
body('de_s3_title')
|
||||
.notEmpty().withMessage('تیتر بخش سوم نباید خالی باشد.'),
|
||||
body('de_s3_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش سوم نباید خالی باشد.'),
|
||||
body('de_s3_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش سوم نباید خالی باشد.'),
|
||||
body('de_s4_text')
|
||||
.notEmpty().withMessage('متن بخش چهارم نباید خالی باشد.'),
|
||||
body('de_last_section_title')
|
||||
.notEmpty().withMessage('تیتر بخش آخر نباید خالی باشد.'),
|
||||
body('de_last_section_text')
|
||||
.notEmpty().withMessage('متن بخش آخر نباید خالی باشد.'),
|
||||
|
||||
// tr
|
||||
body('tr_page_title')
|
||||
.notEmpty().withMessage('تیتر بالای صفحه نباید خالی باشد.'),
|
||||
body('tr_s1_title')
|
||||
.notEmpty().withMessage('تیتر بخش اول نباید خالی باشد.'),
|
||||
body('tr_s1_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش اول نباید خالی باشد.'),
|
||||
body('tr_s2_title')
|
||||
.notEmpty().withMessage('تیتر بخش دوم نباید خالی باشد.'),
|
||||
body('tr_s2_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش دوم نباید خالی باشد.'),
|
||||
body('tr_s2_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش دوم نباید خالی باشد.'),
|
||||
body('tr_s3_title')
|
||||
.notEmpty().withMessage('تیتر بخش سوم نباید خالی باشد.'),
|
||||
body('tr_s3_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش سوم نباید خالی باشد.'),
|
||||
body('tr_s3_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش سوم نباید خالی باشد.'),
|
||||
body('tr_s4_text')
|
||||
.notEmpty().withMessage('متن بخش چهارم نباید خالی باشد.'),
|
||||
body('tr_last_section_title')
|
||||
.notEmpty().withMessage('تیتر بخش آخر نباید خالی باشد.'),
|
||||
body('tr_last_section_text')
|
||||
.notEmpty().withMessage('متن بخش آخر نباید خالی باشد.'),
|
||||
|
||||
// it
|
||||
body('it_page_title')
|
||||
.notEmpty().withMessage('تیتر بالای صفحه نباید خالی باشد.'),
|
||||
body('it_s1_title')
|
||||
.notEmpty().withMessage('تیتر بخش اول نباید خالی باشد.'),
|
||||
body('it_s1_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش اول نباید خالی باشد.'),
|
||||
body('it_s2_title')
|
||||
.notEmpty().withMessage('تیتر بخش دوم نباید خالی باشد.'),
|
||||
body('it_s2_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش دوم نباید خالی باشد.'),
|
||||
body('it_s2_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش دوم نباید خالی باشد.'),
|
||||
body('it_s3_title')
|
||||
.notEmpty().withMessage('تیتر بخش سوم نباید خالی باشد.'),
|
||||
body('it_s3_caption')
|
||||
.notEmpty().withMessage('توضیحات بخش سوم نباید خالی باشد.'),
|
||||
body('it_s3_imageCaption')
|
||||
.notEmpty().withMessage('توضیحات عکس بخش سوم نباید خالی باشد.'),
|
||||
body('it_s4_text')
|
||||
.notEmpty().withMessage('متن بخش چهارم نباید خالی باشد.'),
|
||||
body('it_last_section_title')
|
||||
.notEmpty().withMessage('تیتر بخش آخر نباید خالی باشد.'),
|
||||
body('it_last_section_text')
|
||||
.notEmpty().withMessage('متن بخش آخر نباید خالی باشد.'),
|
||||
|
||||
],
|
||||
(req, res) => {
|
||||
// check validations
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
|
||||
////////////////// catch form data
|
||||
const data = {
|
||||
aboutPage_details: {
|
||||
fa: {
|
||||
page_title: req.body.fa_page_title,
|
||||
s1_title: req.body.fa_s1_title,
|
||||
s1_caption: req.body.fa_s1_caption,
|
||||
s2_title: req.body.fa_s2_title,
|
||||
s2_caption: req.body.fa_s2_caption,
|
||||
s2_imageCaption: req.body.fa_s2_imageCaption,
|
||||
s3_title: req.body.fa_s3_title,
|
||||
s3_caption: req.body.fa_s3_caption,
|
||||
s3_imageCaption: req.body.fa_s3_imageCaption,
|
||||
s4_text: req.body.fa_s4_text,
|
||||
last_section_title: req.body.fa_last_section_title,
|
||||
last_section_text: req.body.fa_last_section_text
|
||||
},
|
||||
en: {
|
||||
page_title: req.body.en_page_title,
|
||||
s1_title: req.body.en_s1_title,
|
||||
s1_caption: req.body.en_s1_caption,
|
||||
s2_title: req.body.en_s2_title,
|
||||
s2_caption: req.body.en_s2_caption,
|
||||
s2_imageCaption: req.body.en_s2_imageCaption,
|
||||
s3_title: req.body.en_s3_title,
|
||||
s3_caption: req.body.en_s3_caption,
|
||||
s3_imageCaption: req.body.en_s3_imageCaption,
|
||||
s4_text: req.body.en_s4_text,
|
||||
last_section_title: req.body.en_last_section_title,
|
||||
last_section_text: req.body.en_last_section_text
|
||||
},
|
||||
de: {
|
||||
page_title: req.body.de_page_title,
|
||||
s1_title: req.body.de_s1_title,
|
||||
s1_caption: req.body.de_s1_caption,
|
||||
s2_title: req.body.de_s2_title,
|
||||
s2_caption: req.body.de_s2_caption,
|
||||
s2_imageCaption: req.body.de_s2_imageCaption,
|
||||
s3_title: req.body.de_s3_title,
|
||||
s3_caption: req.body.de_s3_caption,
|
||||
s3_imageCaption: req.body.de_s3_imageCaption,
|
||||
s4_text: req.body.de_s4_text,
|
||||
last_section_title: req.body.de_last_section_title,
|
||||
last_section_text: req.body.de_last_section_text
|
||||
},
|
||||
tr: {
|
||||
page_title: req.body.tr_page_title,
|
||||
s1_title: req.body.tr_s1_title,
|
||||
s1_caption: req.body.tr_s1_caption,
|
||||
s2_title: req.body.tr_s2_title,
|
||||
s2_caption: req.body.tr_s2_caption,
|
||||
s2_imageCaption: req.body.tr_s2_imageCaption,
|
||||
s3_title: req.body.tr_s3_title,
|
||||
s3_caption: req.body.tr_s3_caption,
|
||||
s3_imageCaption: req.body.tr_s3_imageCaption,
|
||||
s4_text: req.body.tr_s4_text,
|
||||
last_section_title: req.body.tr_last_section_title,
|
||||
last_section_text: req.body.tr_last_section_text
|
||||
},
|
||||
it: {
|
||||
page_title: req.body.it_page_title,
|
||||
s1_title: req.body.it_s1_title,
|
||||
s1_caption: req.body.it_s1_caption,
|
||||
s2_title: req.body.it_s2_title,
|
||||
s2_caption: req.body.it_s2_caption,
|
||||
s2_imageCaption: req.body.it_s2_imageCaption,
|
||||
s3_title: req.body.it_s3_title,
|
||||
s3_caption: req.body.it_s3_caption,
|
||||
s3_imageCaption: req.body.it_s3_imageCaption,
|
||||
s4_text: req.body.it_s4_text,
|
||||
last_section_title: req.body.it_last_section_title,
|
||||
last_section_text: req.body.it_last_section_text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createImages(image, imageName) {
|
||||
if (image) {
|
||||
jimp.read(image.data)
|
||||
.then(img => {
|
||||
img
|
||||
.cover(380, 510)
|
||||
.write(`./static/uploads/images/about/${imageName}`, (err, file) => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let heroFile
|
||||
let heroFileName
|
||||
let s2File
|
||||
let s2FileName
|
||||
let s3File
|
||||
let s3FileName
|
||||
let lastSectionFile
|
||||
let lastSectionFileName
|
||||
|
||||
if (req.files) {
|
||||
if (req.files.page_hero) {
|
||||
heroFile = req.files.page_hero
|
||||
heroFileName = 'image_' + Date.now() + 1 + '.' + heroFile.mimetype.split('/')[1]
|
||||
}
|
||||
if (req.files.s2_image) {
|
||||
s2File = req.files.s2_image
|
||||
s2FileName = 'image_' + Date.now() + 2 + '.' + s2File.mimetype.split('/')[1]
|
||||
}
|
||||
if (req.files.s3_image) {
|
||||
s3File = req.files.s3_image
|
||||
s3FileName = 'image_' + Date.now() + 3 + '.' + s3File.mimetype.split('/')[1]
|
||||
}
|
||||
if (req.files.last_section_image) {
|
||||
lastSectionFile = req.files.last_section_image
|
||||
lastSectionFileName = 'image_' + Date.now() + 4 + '.' + lastSectionFile.mimetype.split('/')[1]
|
||||
}
|
||||
}
|
||||
|
||||
/////////////// save to database
|
||||
if (req.body._id) {
|
||||
if (req.files) {
|
||||
if (heroFile) {
|
||||
if (heroFile.size / 1024 > 500) return res.status(422).json({validation: {page_hero: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
data.page_hero = heroFileName
|
||||
heroFile.mv(`./static/uploads/images/about/${heroFileName}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
if (s2File) {
|
||||
data.s2_image = s2FileName
|
||||
createImages(s2File, s2FileName)
|
||||
}
|
||||
|
||||
if (s3File) {
|
||||
data.s3_image = s3FileName
|
||||
createImages(s3File, s3FileName)
|
||||
}
|
||||
|
||||
if (lastSectionFile) {
|
||||
if (lastSectionFile.size / 1024 > 500) return res.status(422).json({validation: {last_section_image: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
data.last_section_image = lastSectionFileName
|
||||
lastSectionFile.mv(`./static/uploads/images/about/${lastSectionFileName}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
data.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
AboutPageContent.findByIdAndUpdate(req.body._id, data, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
if (req.files) {
|
||||
if (heroFile) {
|
||||
fs.unlink(`./static/${oldData.page_hero}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
if (s2File) {
|
||||
fs.unlink(`./static/${oldData.s2_image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
if (s3File) {
|
||||
fs.unlink(`./static/${oldData.s3_image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
if (lastSectionFile) {
|
||||
fs.unlink(`./static/${oldData.last_section_image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
AboutPageContent.findByIdAndUpdate(req.body._id)
|
||||
.then(data => {
|
||||
return res.json(data)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
if (req.files) {
|
||||
if (heroFile) {
|
||||
if (heroFile.size / 1024 > 500) return res.status(422).json({validation: {page_hero: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
data.page_hero = heroFileName
|
||||
heroFile.mv(`./static/uploads/images/about/${heroFileName}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
} else {
|
||||
return res.status(422).json({validation: {page_hero: {msg: 'عکس بخش اول اجباری است.'}}})
|
||||
}
|
||||
|
||||
if (s2File) {
|
||||
data.s2_image = s2FileName
|
||||
createImages(s2File, s2FileName)
|
||||
} else {
|
||||
return res.status(422).json({validation: {s2_image: {msg: 'عکس بخش دوم اجباری است.'}}})
|
||||
}
|
||||
|
||||
if (s3File) {
|
||||
data.s3_image = s3FileName
|
||||
createImages(s3File, s3FileName)
|
||||
} else {
|
||||
return res.status(422).json({validation: {s3_image: {msg: 'عکس بخش سوم اجباری است.'}}})
|
||||
}
|
||||
|
||||
if (lastSectionFile) {
|
||||
if (lastSectionFile.size / 1024 > 500) return res.status(422).json({validation: {last_section_image: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
data.last_section_image = lastSectionFileName
|
||||
lastSectionFile.mv(`./static/uploads/images/about/${lastSectionFileName}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
} else {
|
||||
return res.status(422).json({validation: {last_section_image: {msg: 'عکس بخش آخر اجباری است.'}}})
|
||||
}
|
||||
} else {
|
||||
return res.status(422).json({
|
||||
validation: {
|
||||
page_hero: {msg: 'عکس بخش اول اجباری است.'},
|
||||
s2_image: {msg: 'عکس بخش دوم اجباری است.'},
|
||||
s3_image: {msg: 'عکس بخش سوم اجباری است.'},
|
||||
last_section_image: {msg: 'عکس بخش آخر اجباری است.'}
|
||||
}
|
||||
})
|
||||
}
|
||||
data.created_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
const aboutContent = new AboutPageContent(data)
|
||||
aboutContent.save((err, data) => {
|
||||
if (err) return res.status(500).json(err)
|
||||
return res.json(data)
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.get = [
|
||||
(req, res) => {
|
||||
AboutPageContent.findOne({}, (err, data) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
return res.json(data)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,137 @@
|
||||
const Admin = require('../models/admin/Admin')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const bcrypt = require('bcryptjs')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const config = require('../config')
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// register
|
||||
module.exports.register = [
|
||||
[
|
||||
body('name')
|
||||
.isLength({min: 4}).withMessage('حداقل 4 کاراکتر'),
|
||||
|
||||
body('username')
|
||||
.isLength({min: 4}).withMessage('حداقل 4 کاراکتر')
|
||||
.custom((value, {req}) => {
|
||||
return Admin.findOne({username: value})
|
||||
.then(admin => {
|
||||
if (admin && admin.username === value) return Promise.reject('این نام کاربری از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('password')
|
||||
.isLength({min: 4}).withMessage('حداقل 4 کاراکتر')
|
||||
.custom((value, {req}) => {
|
||||
return value === req.body.password_confirmation
|
||||
}).withMessage('پسورد ها یکی نیست.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {}
|
||||
data.name = req.body.name
|
||||
data.username = req.body.username
|
||||
data.scope = 'admin'
|
||||
data.created_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(req.body.password, salt, (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
data.password = hash
|
||||
|
||||
const admin = new Admin(data)
|
||||
admin.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'Admin added.'})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// login
|
||||
module.exports.login = [
|
||||
[
|
||||
body('username')
|
||||
.isLength({min: 4}).withMessage('حداقل 4 کاراکتر')
|
||||
.custom((value, {req}) => {
|
||||
return Admin.findOne({username: value})
|
||||
.then(admin => {
|
||||
if (!admin) return Promise.reject('ادمینی با این نام وجود ندارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('password')
|
||||
.isLength({min: 4}).withMessage('حداقل 4 کاراکتر'),
|
||||
|
||||
body('remember_me')
|
||||
.exists().withMessage('پارامتر remember_me الزامی است.')
|
||||
.bail()
|
||||
.isBoolean().withMessage('مقدار باید از جنس Boolean باشد.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
Admin.findOne({username: req.body.username}, (err, user) => {
|
||||
if (err) console.log(err)
|
||||
bcrypt.compare(req.body.password, user.password, (err, isMatch) => {
|
||||
if (err) console.log(err)
|
||||
if (!isMatch) return res.status(422).json({validation: {password: {msg: 'پسورد اشتباه است.'}}})
|
||||
|
||||
let token
|
||||
if (req.body.remember_me) token = jwt.sign({_id: user._id}, config.secretKey)
|
||||
else token = jwt.sign({_id: user._id}, config.secretKey, {expiresIn: '1h'})
|
||||
|
||||
user.token = token
|
||||
user.markModified('token')
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({token: token})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// logout
|
||||
module.exports.logout = [
|
||||
(req, res) => {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
Admin.findOneAndUpdate({token: token}, {token: null}, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
if (oldData) return res.json({message: 'You are logged out.'})
|
||||
return res.status(401).json({message: 'Your not logged in'})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: 'Your not logged in'})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// get user
|
||||
module.exports.getUser = [
|
||||
config.isAdmin,
|
||||
(req, res) => {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
jwt.verify(token, config.secretKey, (err, decoded) => {
|
||||
if (err) return res.status(401).json({message: 'unauthenticated'})
|
||||
Admin.findById(decoded._id, (err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({user: data})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: 'unauthenticated'})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// delete
|
||||
@@ -0,0 +1,202 @@
|
||||
const BlogCategory = require('../models/blog/BlogCategory')
|
||||
const BlogPost = require('../models/blog/BlogPost')
|
||||
const dateformat = require('dateformat')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
body('fa_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
|
||||
if (category) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('en_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
|
||||
if (category) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('de_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.de.name': value}).then(category => {
|
||||
if (category) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('tr_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.tr.name': value}).then(category => {
|
||||
if (category) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('it_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.it.name': value}).then(category => {
|
||||
if (category) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const blogCategory = new BlogCategory({
|
||||
blogCategory_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name
|
||||
}
|
||||
},
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
blogCategory.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'دسته بندی اضافه شد.'})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
BlogCategory.find({}, (err, categories) => {
|
||||
if (err) return res.status(500).json({message: err})
|
||||
return res.json(categories)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
BlogCategory.findById(req.params.id, (err, category) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
return res.json(category)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.update = [
|
||||
[
|
||||
body('fa_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.fa.name': value}).then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('en_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.en.name': value}).then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('de_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.de.name': value}).then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('tr_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.tr.name': value}).then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('it_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogCategory.findOne({'blogCategory_details.it.name': value}).then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('این نام از قبل وجود دارد.')
|
||||
return true
|
||||
})
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
blogCategory_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name
|
||||
}
|
||||
},
|
||||
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
BlogCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'دسته بندی بروزرسانی شد.'})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
BlogPost.find({category: req.params.id}, (err, categories) => {
|
||||
if (err) console.log(err)
|
||||
if (!categories.length) {
|
||||
BlogCategory.findByIdAndDelete(req.params.id, (err) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
return res.json({message: 'دسته بندی حذف شد.'})
|
||||
})
|
||||
} else {
|
||||
return res.status(500).json({message: 'نمیتوان دسته بندی هایی که دارای پست هستند را پاک کرد.'})
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,378 @@
|
||||
const BlogPost = require('../models/blog/BlogPost')
|
||||
const dateformat = require('dateformat')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const fs = require('fs')
|
||||
const jimp = require('jimp')
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
// title
|
||||
body('fa_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
|
||||
if (post) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('en_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
|
||||
if (post) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('de_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.de.title': value}).then(post => {
|
||||
if (post) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('tr_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.tr.title': value}).then(post => {
|
||||
if (post) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('it_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.it.title': value}).then(post => {
|
||||
if (post) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
|
||||
// description
|
||||
body('fa_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('en_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('de_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('tr_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('it_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
// short description
|
||||
body('fa_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('en_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('de_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('tr_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('it_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
|
||||
body('category')
|
||||
.notEmpty().withMessage('دسته بندی را انتخاب کنید.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
let cover
|
||||
let coverName
|
||||
|
||||
// 305 X 170
|
||||
// 1370 x 556
|
||||
|
||||
if (req.files && req.files.cover) {
|
||||
cover = req.files.cover
|
||||
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
|
||||
|
||||
if (cover.size / 1024 > 500) return res.status(422).json({validation: {cover: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
} else {
|
||||
return res.status(422).json({validation: {cover: {msg: 'کاور اجباری است.'}}})
|
||||
}
|
||||
|
||||
jimp.read(cover.data)
|
||||
.then(img => {
|
||||
img
|
||||
.cover(1370, 688)
|
||||
.write(`./static/uploads/images/blog/${coverName}`)
|
||||
.resize(305, jimp.AUTO)
|
||||
.cover(305, 170)
|
||||
.write(`./static/uploads/images/blog/thumb_${coverName}`)
|
||||
})
|
||||
|
||||
const data = {
|
||||
post_details: {
|
||||
fa: {
|
||||
title: req.body.fa_title,
|
||||
description: req.body.fa_description,
|
||||
short_description: req.body.fa_short_description
|
||||
},
|
||||
en: {
|
||||
title: req.body.en_title,
|
||||
description: req.body.en_description,
|
||||
short_description: req.body.en_short_description
|
||||
},
|
||||
de: {
|
||||
title: req.body.de_title,
|
||||
description: req.body.de_description,
|
||||
short_description: req.body.de_short_description
|
||||
},
|
||||
tr: {
|
||||
title: req.body.tr_title,
|
||||
description: req.body.tr_description,
|
||||
short_description: req.body.tr_short_description
|
||||
},
|
||||
it: {
|
||||
title: req.body.it_title,
|
||||
description: req.body.it_description,
|
||||
short_description: req.body.it_short_description
|
||||
}
|
||||
},
|
||||
cover: coverName,
|
||||
published: req.body.published,
|
||||
category: req.body.category,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
const post = new BlogPost(data)
|
||||
post.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'پست با موفقیت اضافه شد.'})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
BlogPost.find({}).sort({_id: -1}).exec((err, posts) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(posts)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
BlogPost.findById(req.params.id, (err, post) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(post)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.update = [
|
||||
[
|
||||
// title
|
||||
body('fa_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.fa.title': value}).then(post => {
|
||||
if (post && post._id.toString() !== req.params.id) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('en_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.en.title': value}).then(post => {
|
||||
if (post && post._id.toString() !== req.params.id) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('de_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.de.title': value}).then(post => {
|
||||
if (post && post._id.toString() !== req.params.id) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('tr_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.tr.title': value}).then(post => {
|
||||
if (post && post._id.toString() !== req.params.id) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
body('it_title')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 60}).withMessage('حداکثر 60 کاراکتر مجاز است.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return BlogPost.findOne({'post_details.it.title': value}).then(post => {
|
||||
if (post && post._id.toString() !== req.params.id) return Promise.reject('عنوان تکراری است.')
|
||||
return true
|
||||
})
|
||||
}),
|
||||
|
||||
// description
|
||||
body('fa_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('en_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('de_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('tr_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
body('it_description')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
// short description
|
||||
body('fa_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('en_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('de_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('tr_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
body('it_short_description')
|
||||
.notEmpty().withMessage('توضیح کوتاه نباید خالی باشد.')
|
||||
.bail()
|
||||
.isLength({max: 120}).withMessage('حداکثر 120 کاراکتر مجاز است.'),
|
||||
|
||||
body('category')
|
||||
.notEmpty().withMessage('دسته بندی را انتخاب کنید.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
|
||||
const data = {
|
||||
post_details: {
|
||||
fa: {
|
||||
title: req.body.fa_title,
|
||||
description: req.body.fa_description,
|
||||
short_description: req.body.fa_short_description
|
||||
},
|
||||
en: {
|
||||
title: req.body.en_title,
|
||||
description: req.body.en_description,
|
||||
short_description: req.body.en_short_description
|
||||
},
|
||||
de: {
|
||||
title: req.body.de_title,
|
||||
description: req.body.de_description,
|
||||
short_description: req.body.de_short_description
|
||||
},
|
||||
tr: {
|
||||
title: req.body.tr_title,
|
||||
description: req.body.tr_description,
|
||||
short_description: req.body.tr_short_description
|
||||
},
|
||||
it: {
|
||||
title: req.body.it_title,
|
||||
description: req.body.it_description,
|
||||
short_description: req.body.it_short_description
|
||||
}
|
||||
},
|
||||
published: req.body.published,
|
||||
category: req.body.category,
|
||||
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
// 305 X 170
|
||||
// 1370 x 556
|
||||
let cover
|
||||
let coverName
|
||||
|
||||
if (req.files && req.files.cover) {
|
||||
cover = req.files.cover
|
||||
coverName = 'blog_' + Date.now() + '.' + cover.mimetype.split('/')[1]
|
||||
|
||||
if (cover.size / 1024 > 500) return res.status(422).json({validation: {cover: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}})
|
||||
data.cover = coverName
|
||||
jimp.read(cover.data)
|
||||
.then(img => {
|
||||
img
|
||||
.cover(1370, 688)
|
||||
.write(`./static/uploads/images/blog/${coverName}`)
|
||||
.resize(305, jimp.AUTO)
|
||||
.cover(305, 170)
|
||||
.write(`./static/uploads/images/blog/thumb_${coverName}`)
|
||||
})
|
||||
}
|
||||
|
||||
BlogPost.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
if (cover && cover.data) fs.unlink(`./static/${oldData.cover}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
if (cover && cover.data) fs.unlink(`./static/${oldData.thumb}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'پست با موفقیت بروزرسانی شد.'})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
BlogPost.findByIdAndDelete(req.params.id, (err, post) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
fs.unlink(`./static/${post.cover}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
fs.unlink(`./static/${post.thumb}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'پست حذف شد.'})
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,81 @@
|
||||
const Broadcast = require('../models/Broadcast')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
body('title')
|
||||
.isLength({min: 2}).withMessage('حداقل 2 کاراکتر'),
|
||||
|
||||
body('message')
|
||||
.isLength({min: 10}).withMessage('حداقل 10 کاراکتر'),
|
||||
|
||||
body('locale')
|
||||
.notEmpty().withMessage('زبان پیام را انتخاب کنید')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
title: req.body.title,
|
||||
message: req.body.message,
|
||||
admin_id: req.body.admin_id,
|
||||
locale: req.body.locale,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
const broadcast = new Broadcast(data)
|
||||
broadcast.save((err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(data)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
Broadcast.find({})
|
||||
.then(messages => {
|
||||
return res.json(messages)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
Broadcast.findById(req.params.id)
|
||||
.then(message => {
|
||||
if (!message.read.includes(req.body.user_id)) {
|
||||
message.read.push(req.body.user_id)
|
||||
message.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json(message)
|
||||
})
|
||||
} else {
|
||||
return res.json(message)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
Broadcast.findByIdAndDelete(req.params.id)
|
||||
.then(message => {
|
||||
return res.json({message: 'Message deleted.'})
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,107 @@
|
||||
const ContactPageMessage = require('../models/ContactPageMessage')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const v_m = require('../validation_messages')
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
body('first_name')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.first_name
|
||||
})
|
||||
.bail()
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('last_name')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.last_name
|
||||
})
|
||||
.bail()
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('phone_number')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.phone_number
|
||||
})
|
||||
.bail()
|
||||
.isNumeric()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.phone_number
|
||||
}),
|
||||
|
||||
body('email')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email
|
||||
})
|
||||
.bail()
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
}),
|
||||
|
||||
body('message')
|
||||
.isLength({min: 50})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min50
|
||||
})
|
||||
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
first_name: req.body.first_name,
|
||||
last_name: req.body.last_name,
|
||||
phone_number: req.body.phone_number,
|
||||
email: req.body.email,
|
||||
message: req.body.message,
|
||||
user_id: req.body.user_id,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
const message = new ContactPageMessage(data)
|
||||
message.save((err, message) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
ContactPageMessage.find({}).select('-message')
|
||||
.then(messages => {
|
||||
return res.json(messages)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
ContactPageMessage.findById(req.params.id)
|
||||
.then(message => {
|
||||
message.read = true
|
||||
message.save()
|
||||
return res.json(message)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,89 @@
|
||||
const Gallery = require('../models/Gallery')
|
||||
const jimp = require('jimp')
|
||||
const fs = require('fs')
|
||||
const dateFormat = require('dateformat')
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////// create image
|
||||
module.exports.create = [
|
||||
(req, res) => {
|
||||
let file
|
||||
let fileName
|
||||
|
||||
////////////// validate image upload
|
||||
if (req.files) {
|
||||
file = req.files.image
|
||||
fileName = 'gallery_' + Date.now() + '.' + file.mimetype.split('/')[1]
|
||||
jimp.read(file.data)
|
||||
.then(img => {
|
||||
img
|
||||
.cover(940, 620, jimp.HORIZONTAL_ALIGN_CENTER | jimp.VERTICAL_ALIGN_MIDDLE)
|
||||
.write(`./static/uploads/images/gallery/${fileName}`, (err, img) => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
.resize(335, jimp.AUTO)
|
||||
.write(`./static/uploads/images/gallery/thumb/thumb_${fileName}`, (err, img) => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
|
||||
let gallery = new Gallery({
|
||||
image: fileName,
|
||||
created_at: dateFormat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
gallery.save((err, image) => {
|
||||
if (err) return res.status(500).json(err)
|
||||
Gallery.find({})
|
||||
.then(images => {
|
||||
return res.json(images)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'عکس اجباری است'}}})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////// get all images
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
Gallery.find({}, (err, images) => {
|
||||
if (err) return res.json({errors: err})
|
||||
return res.json(images)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////// get one image
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
Gallery.findById(req.params.id, (err, image) => {
|
||||
if (err) return res.json({errors: err})
|
||||
return res.json(image)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////// delete image
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
Gallery.findByIdAndRemove(req.params.id, (err, data) => {
|
||||
if (err) return res.json({error: err})
|
||||
fs.unlink(`./static/${data.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
fs.unlink(`./static/${data.thumb}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'تصویر حذف شد'})
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,36 @@
|
||||
const locales = [
|
||||
{
|
||||
name: 'فارسی',
|
||||
value: 'fa',
|
||||
currency: 'ريال'
|
||||
},
|
||||
{
|
||||
name: 'انگلیسی',
|
||||
value: 'en',
|
||||
currency: 'USD'
|
||||
},
|
||||
{
|
||||
name: 'آلمانی',
|
||||
value: 'de',
|
||||
currency: 'EUR'
|
||||
},
|
||||
{
|
||||
name: 'ترکی',
|
||||
value: 'tr',
|
||||
currency: 'TL'
|
||||
},
|
||||
{
|
||||
name: 'ایتالیایی',
|
||||
value: 'it',
|
||||
currency: 'EUR'
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.locales = locales
|
||||
|
||||
module.exports.get = [
|
||||
(req, res) => {
|
||||
return res.json(locales)
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
const Cart_Item = require('../models/user/Cart_item')
|
||||
const Order = require('../models/user/Order')
|
||||
const User = require('../models/user/User')
|
||||
const localeController = require('./localeController')
|
||||
const Product = require('../models/product/Product')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const v_m = require('../validation_messages')
|
||||
|
||||
////////////////////////////////////// cart
|
||||
module.exports.addToCart = [
|
||||
[
|
||||
body('user_id')
|
||||
.custom((value, {req}) => {
|
||||
return User.findById(value)
|
||||
.then(user => {
|
||||
if (user) return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject(v_m[req.body.locale].not_found.user_id)
|
||||
})
|
||||
}),
|
||||
|
||||
body('product_id')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findById(value)
|
||||
.then(product => {
|
||||
if (product) return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject(v_m[req.body.locale].not_found.item_id)
|
||||
})
|
||||
}),
|
||||
body('quantity')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.quantity
|
||||
})
|
||||
.bail()
|
||||
.isNumeric()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.number
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json(errors)
|
||||
|
||||
Cart_Item.findOne({product_id: req.body.product_id, user_id: req.body.user_id})
|
||||
.then(item => {
|
||||
item.quantity = Number(item.quantity) + Number(req.body.quantity)
|
||||
item.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
item.markModified('quantity')
|
||||
item.markModified('updated_at')
|
||||
item.save()
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
.catch(err => {
|
||||
const data = {
|
||||
user_id: req.body.user_id,
|
||||
product_id: req.body.product_id,
|
||||
quantity: req.body.quantity,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
const cartItem = new Cart_Item(data)
|
||||
cartItem.save((err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getCartItems = [
|
||||
(req, res) => {
|
||||
Cart_Item.find({user_id: req.params.user_id}, (err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(data)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.updateCart = [
|
||||
(req, res) => {
|
||||
Cart_Item.findById(req.params.item_id)
|
||||
.then(item => {
|
||||
item.quantity = Number(req.body.quantity)
|
||||
item.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
item.markModified('quantity')
|
||||
item.markModified('updated_at')
|
||||
item.save()
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json({message: v_m[req.body.locale].not_found.item_id})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.deleteFromCart = [
|
||||
(req, res) => {
|
||||
Cart_Item.findByIdAndDelete(req.params.item_id)
|
||||
.then(item => {
|
||||
Cart_Item.find({user_id: item.user_id})
|
||||
.then(items => {
|
||||
return res.json(items)
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json({message: v_m['en'].not_found.item_id})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
////////////////////////////////////// order
|
||||
module.exports.addOrder = [
|
||||
[
|
||||
body('user_id')
|
||||
.custom((value, {req}) => {
|
||||
return User.findById(value)
|
||||
.then(user => {
|
||||
return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject(v_m[req.body.locale].not_found.user_id)
|
||||
})
|
||||
})
|
||||
],
|
||||
//////////////////// validation step
|
||||
(req, res, next) => {
|
||||
Cart_Item.find({user_id: req.body.user_id})
|
||||
.then(items => {
|
||||
// check if cart is not empty
|
||||
if (items.length) {
|
||||
// check product stock
|
||||
let outOfRun = []
|
||||
items.forEach(async (item, index) => {
|
||||
await Product.findById(item.product_id)
|
||||
.then(product => {
|
||||
if (product.stock < item.quantity) {
|
||||
outOfRun.push({
|
||||
product_id: product._id,
|
||||
category_id: product.category,
|
||||
stock: product.stock
|
||||
})
|
||||
item.remove()
|
||||
}
|
||||
if (index + 1 === items.length) {
|
||||
if (!outOfRun.length) return next()
|
||||
else return res.status(422).json(outOfRun)
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(404).json({message: v_m[req.body.locale].response.cart_empty})
|
||||
}
|
||||
})
|
||||
},
|
||||
//////////////////// save order
|
||||
(req, res) => {
|
||||
Cart_Item.find({user_id: req.body.user_id})
|
||||
.then(items => {
|
||||
// save the order
|
||||
const orderData = {
|
||||
user_id: req.body.user_id,
|
||||
number: Date.now(),
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
const order = new Order(orderData)
|
||||
order.save((err, order) => {
|
||||
if (err) console.log(err)
|
||||
|
||||
// get price unit for items
|
||||
let unit = localeController.locales.filter(item => {
|
||||
return item.value === req.body.locale
|
||||
})[0].currency
|
||||
|
||||
// add incomplete status to order
|
||||
order.statuses.push({
|
||||
status: 'incomplete',
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
|
||||
// add each item (Cart_Item result) to the order (saved Order result) and then remove it
|
||||
items.forEach((item, index) => {
|
||||
|
||||
// get the price of each item depend on order locale
|
||||
Product.findById(item.product_id).then(product => {
|
||||
let data = {
|
||||
product_id: item.product_id,
|
||||
quantity: item.quantity,
|
||||
price: product.product_details[req.body.locale].price,
|
||||
price_unit: unit,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
order.order_items.push(data)
|
||||
// reduce the product stock
|
||||
product.stock = Number(product.stock) - Number(item.quantity)
|
||||
product.save()
|
||||
item.remove()
|
||||
if (index + 1 === items.length) {
|
||||
order.save()
|
||||
return res.json(order)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.addAddressToOrder = [
|
||||
(req, res) => {
|
||||
Order.findById(req.params.order_id)
|
||||
.then(order => {
|
||||
if (!order.address) {
|
||||
User.findOne({'addresses._id': req.body.address_id})
|
||||
.then(user => {
|
||||
order.address = user.addresses.id(req.body.address_id)
|
||||
// add processing status to order
|
||||
order.statuses.push({
|
||||
status: 'processing',
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
order.save()
|
||||
return res.json(order)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
} else {
|
||||
return res.status(500).json({message: v_m[req.body.locale].response.already_has_address})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
return res.status(404).json({message: v_m[req.body.locale].not_found.order_id})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.addStatusToOrder = [
|
||||
(req, res) => {
|
||||
Order.findById(req.params.order_id)
|
||||
.then(order => {
|
||||
order.statuses.push({
|
||||
status: req.body.status,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
order.save()
|
||||
return res.json(order)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getOrders = [
|
||||
(req, res) => {
|
||||
Order.find({user_id: req.params.user_id})
|
||||
.then(orders => {
|
||||
return res.json(orders)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getOneOrder = [
|
||||
(req, res) => {
|
||||
Order.findById(req.params.order_id)
|
||||
.then(order => {
|
||||
return res.json(order)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
////////////////////////////////////// get list of all orders for admin
|
||||
module.exports.getAllOrders = [
|
||||
(req, res) => {
|
||||
Order.find({})
|
||||
.then(orders => {
|
||||
return res.json(orders)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,363 @@
|
||||
const ProductCategory = require('../models/product/ProductCategory')
|
||||
const Product = require('../models/product/Product')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const jimp = require('jimp')
|
||||
const fs = require('fs')
|
||||
|
||||
|
||||
module.exports.create = [
|
||||
[
|
||||
body('fa_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.fa.name': value})
|
||||
.then(category => {
|
||||
if (category) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('en_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.en.name': value})
|
||||
.then(category => {
|
||||
if (category) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('de_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.de.name': value})
|
||||
.then(category => {
|
||||
if (category) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('tr_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.tr.name': value})
|
||||
.then(category => {
|
||||
if (category) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('it_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.it.name': value})
|
||||
.then(category => {
|
||||
if (category) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('fa_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('en_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('de_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('tr_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('it_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.')
|
||||
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
|
||||
let image
|
||||
let imageName
|
||||
let cover
|
||||
let coverName
|
||||
|
||||
if (req.files) {
|
||||
if (req.files.image) {
|
||||
image = req.files.image
|
||||
imageName = 'categoryImage_' + Date.now() + '.' + image.mimetype.split('/')[1]
|
||||
if (image.mimetype.split('/')[1] !== 'png') return res.status(422).json({validation: {image: {msg: 'فرمت عکس باید png باشد.'}}})
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'عکس اجباری است.'}}})
|
||||
}
|
||||
if (req.files.cover) {
|
||||
cover = req.files.cover
|
||||
coverName = 'categoryCover_' + Date.now() + '.' + cover.mimetype.split('/')[1]
|
||||
if (cover.size / 1024 > 500) return res.status(422).json({validation: {cover: {msg: 'حجم کاور نباید بیشتر از 500 کیلوبایت باشد'}}})
|
||||
cover.mv(`./static/uploads/images/products/category/${coverName}`)
|
||||
} else {
|
||||
return res.status(422).json({validation: {cover: {msg: 'کاور اجباری است.'}}})
|
||||
}
|
||||
} else {
|
||||
return res.status(422).json({
|
||||
validation: {
|
||||
image: {msg: 'عکس اجباری است.'},
|
||||
cover: {msg: 'کاور اجباری است.'}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const data = {
|
||||
cover: coverName,
|
||||
category_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name,
|
||||
caption: req.body.fa_caption
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name,
|
||||
caption: req.body.en_caption
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name,
|
||||
caption: req.body.de_caption
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name,
|
||||
caption: req.body.tr_caption
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name,
|
||||
caption: req.body.it_caption
|
||||
}
|
||||
},
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
jimp.read(image.data).then(img => {
|
||||
img
|
||||
.cover(380, 230)
|
||||
.write(`./static/uploads/images/products/category/${imageName}`, err => {
|
||||
if (err) console.log(err)
|
||||
data.image = imageName
|
||||
|
||||
const category = new ProductCategory(data)
|
||||
category.save(err => {
|
||||
if (err) return res.status(500).json({message: err})
|
||||
return res.json({message: 'دسته بندی با موفقیت ثبت شد.'})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
ProductCategory.find({}, (err, categories) => {
|
||||
if (err) return res.status(500).json({message: err})
|
||||
return res.json(categories)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
ProductCategory.findById(req.params.id, (err, category) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(category)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.update = [
|
||||
[
|
||||
body('fa_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.fa.name': value})
|
||||
.then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('en_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.en.name': value})
|
||||
.then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('de_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.de.name': value})
|
||||
.then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('tr_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.tr.name': value})
|
||||
.then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('it_name')
|
||||
.notEmpty().withMessage('نام نباید خالی باشد.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return ProductCategory.findOne({'category_details.it.name': value})
|
||||
.then(category => {
|
||||
if (category && category._id.toString() !== req.params.id) return Promise.reject('دسته بندی با این نام از قبل وجود دارد')
|
||||
return true
|
||||
})
|
||||
}
|
||||
),
|
||||
|
||||
body('fa_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('en_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('de_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('tr_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.'),
|
||||
|
||||
body('it_caption')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد.')
|
||||
],
|
||||
(req, res) => {
|
||||
// check validation results
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
|
||||
let image
|
||||
let imageName
|
||||
let cover
|
||||
let coverName
|
||||
|
||||
const data = {
|
||||
category_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name,
|
||||
caption: req.body.fa_caption
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name,
|
||||
caption: req.body.en_caption
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name,
|
||||
caption: req.body.de_caption
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name,
|
||||
caption: req.body.tr_caption
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name,
|
||||
caption: req.body.it_caption
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (req.files) {
|
||||
if (req.files.image) {
|
||||
image = req.files.image
|
||||
imageName = 'categoryImage_' + Date.now() + '.' + image.mimetype.split('/')[1]
|
||||
if (image.mimetype.split('/')[1] !== 'png') return res.status(422).json({validation: {image: {msg: 'فرمت عکس باید png باشد.'}}})
|
||||
data.image = imageName
|
||||
|
||||
jimp.read(image.data).then(img => {
|
||||
img
|
||||
.cover(380, 230)
|
||||
.write(`./static/uploads/images/products/category/${imageName}`, err => {
|
||||
if (err) console.log(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
if (req.files.cover) {
|
||||
cover = req.files.cover
|
||||
coverName = 'categoryCover_' + Date.now() + '.' + cover.mimetype.split('/')[1]
|
||||
if (cover.size / 1024 > 500) return res.status(422).json({validation: {cover: {msg: 'حجم کاور نباید بیشتر از 500 کیلوبایت باشد'}}})
|
||||
cover.mv(`./static/uploads/images/products/category/${coverName}`)
|
||||
data.cover = coverName
|
||||
}
|
||||
}
|
||||
|
||||
ProductCategory.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
if (image && image.data) fs.unlink(`./static/${oldData.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
if (cover && cover.data) fs.unlink(`./static/${oldData.cover}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
ProductCategory.findById(oldData._id)
|
||||
.then(category => {
|
||||
return res.json(category)
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
Product.findOne({category: req.params.id}, (err, product) => {
|
||||
if (err) console.log(err)
|
||||
if (product) return res.status(400).json({message: 'این دسته بندی دارای محصول است.'})
|
||||
else {
|
||||
ProductCategory.findByIdAndDelete(req.params.id, (err, category) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
if (category) {
|
||||
fs.unlink(`./static/${category.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
fs.unlink(`./static/${category.cover}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'دسته بندی حذف شد.'})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,535 @@
|
||||
const Product = require('../models/product/Product')
|
||||
const CartItem = require('../models/user/Cart_item')
|
||||
const Order = require('../models/user/Order')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const jimp = require('jimp')
|
||||
const fs = require('fs')
|
||||
|
||||
|
||||
////////////////////////////////////////// products controllers
|
||||
module.exports.createProduct = [
|
||||
[
|
||||
body('fa_name')
|
||||
.isLength({min: 2}).withMessage('حداقل 2 کاراکتر')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.fa.name': value})
|
||||
.then(product => {
|
||||
if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('en_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.en.name': value})
|
||||
.then(product => {
|
||||
if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
|
||||
body('de_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.de.name': value})
|
||||
.then(product => {
|
||||
if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
|
||||
body('tr_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.tr.name': value})
|
||||
.then(product => {
|
||||
if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
|
||||
body('it_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.it.name': value})
|
||||
.then(product => {
|
||||
if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('fa_description')
|
||||
.isLength({min: 2}).withMessage('حداقل 2 کاراکتر'),
|
||||
|
||||
body('fa_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('en_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('de_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('tr_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('it_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('stock')
|
||||
.notEmpty().withMessage('موجودی را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('موجودی باید از جنس عدد باشد'),
|
||||
|
||||
body('category')
|
||||
.notEmpty().withMessage('دسته بندی را انتخاب کنید.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
let image
|
||||
let imageName
|
||||
if (req.files && req.files.image) {
|
||||
image = req.files.image
|
||||
imageName = 'product_' + Date.now() + '.' + image.mimetype.split('/')[1]
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'عکس اجباری است.'}}})
|
||||
}
|
||||
|
||||
const data = {
|
||||
price: req.body.price,
|
||||
stock: req.body.stock,
|
||||
category: req.body.category,
|
||||
product_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name,
|
||||
description: req.body.fa_description,
|
||||
price: req.body.fa_price
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name,
|
||||
description: req.body.en_description,
|
||||
price: req.body.en_price
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name,
|
||||
description: req.body.de_description,
|
||||
price: req.body.de_price
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name,
|
||||
description: req.body.it_description,
|
||||
price: req.body.it_price
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name,
|
||||
description: req.body.tr_description,
|
||||
price: req.body.tr_price
|
||||
}
|
||||
},
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
jimp.read(image.data)
|
||||
.then(img => {
|
||||
img
|
||||
.resize(250, jimp.AUTO)
|
||||
.cover(250, 250)
|
||||
.write(`./static/uploads/images/products/${imageName}`)
|
||||
|
||||
//// write to database
|
||||
data.image = imageName
|
||||
const product = new Product(data)
|
||||
product.save((err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(data)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getAllProductsByCategory = [
|
||||
(req, res) => {
|
||||
Product.find({category: req.params.category})
|
||||
.select('-product_features -product_images -created_at -updated_at')
|
||||
.exec((err, products) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(products)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getAllProducts = [
|
||||
(req, res) => {
|
||||
Product.find({}).select('image stock category product_details').exec((err, products) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(products)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getOneProduct = [
|
||||
async (req, res) => {
|
||||
await Product.findById(req.params.id, async (err, product) => {
|
||||
if (err) return res.status(404).json({message: err})
|
||||
return res.json(product)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.updateProduct = [
|
||||
[
|
||||
body('fa_name')
|
||||
.isLength({min: 2}).withMessage('حداقل 2 کاراکتر')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.fa.name': value})
|
||||
.then(product => {
|
||||
if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('en_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.en.name': value})
|
||||
.then(product => {
|
||||
if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('de_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.de.name': value})
|
||||
.then(product => {
|
||||
if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('tr_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.tr.name': value})
|
||||
.then(product => {
|
||||
if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('it_name')
|
||||
.if((value, {req}) => value !== '')
|
||||
.custom((value, {req}) => {
|
||||
return Product.findOne({'product_details.it.name': value})
|
||||
.then(product => {
|
||||
if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.')
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('fa_description')
|
||||
.isLength({min: 2}).withMessage('حداقل 2 کاراکتر'),
|
||||
|
||||
body('fa_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('en_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('de_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('tr_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('it_price')
|
||||
.notEmpty().withMessage('قیمت را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('قیمت باید از جنس عدد باشد'),
|
||||
|
||||
body('stock')
|
||||
.notEmpty().withMessage('موجودی را وارد کنید.')
|
||||
.bail()
|
||||
.isNumeric().withMessage('موجودی باید از جنس عدد باشد'),
|
||||
|
||||
body('category')
|
||||
.notEmpty().withMessage('دسته بندی را انتخاب کنید.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
price: req.body.price,
|
||||
stock: req.body.stock,
|
||||
category: req.body.category,
|
||||
product_details: {
|
||||
fa: {
|
||||
name: req.body.fa_name,
|
||||
description: req.body.fa_description,
|
||||
price: req.body.fa_price
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name,
|
||||
description: req.body.en_description,
|
||||
price: req.body.en_price
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name,
|
||||
description: req.body.de_description,
|
||||
price: req.body.de_price
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name,
|
||||
description: req.body.it_description,
|
||||
price: req.body.it_price
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name,
|
||||
description: req.body.tr_description,
|
||||
price: req.body.tr_price
|
||||
}
|
||||
},
|
||||
updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
|
||||
let image
|
||||
let imageName
|
||||
if (req.files && req.files.image) {
|
||||
image = req.files.image
|
||||
imageName = 'product_' + Date.now() + '.' + image.mimetype.split('/')[1]
|
||||
data.image = imageName
|
||||
|
||||
jimp.read(image.data)
|
||||
.then(img => {
|
||||
img
|
||||
.resize(250, jimp.AUTO)
|
||||
.cover(250, 250)
|
||||
.write(`./static/uploads/images/products/${imageName}`)
|
||||
|
||||
Product.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
fs.unlink(`./static/${oldData.image}`, (err) => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'product updated.'})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
Product.findByIdAndUpdate(req.params.id, data, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'product updated.'})
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.deleteProduct = [
|
||||
(req, res) => {
|
||||
CartItem.findOne({product_id: req.params.id}, (err, item) => {
|
||||
if (err) console.log(err)
|
||||
if (item) {
|
||||
return res.status(401).json({message: 'این محصول درون سبد خرید ثبت شده و نمیتوان آن را حذف کرد.'})
|
||||
} else {
|
||||
Order.findOne({'order_items.product_id': req.params.id}, (err, order) => {
|
||||
if (err) console.log(err)
|
||||
if (order) {
|
||||
return res.status(401).json({message: 'این محصول درون سفارش ثبت شده و نمیتوان آن را حذف کرد.'})
|
||||
} else {
|
||||
Product.findByIdAndDelete(req.params.id, (err, product) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: 'محصول با موفقیت حذف شد.'})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
////////////////////////////////////////// products images controllers
|
||||
module.exports.createProductImage = [
|
||||
[
|
||||
body('product_id')
|
||||
.notEmpty().withMessage('مشخصات محصول را وارد کنید.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return Product.findById(value)
|
||||
.then(product => {
|
||||
return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject('محصولی با این مشخصات وجود ندارد.')
|
||||
})
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: {images: errors.mapped()}})
|
||||
|
||||
let image
|
||||
let imageName
|
||||
if (req.files && req.files.image) {
|
||||
image = req.files.image
|
||||
imageName = 'productImages_' + Date.now() + '.' + image.mimetype.split('/')[1]
|
||||
|
||||
if (image.size / 1024 > 500) return res.status(422).json({validation: {images: {image: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}}})
|
||||
|
||||
|
||||
jimp.read(image.data)
|
||||
.then(img => {
|
||||
img
|
||||
.resize(250, jimp.AUTO)
|
||||
.cover(250, 250)
|
||||
.write(`./static/uploads/images/products/gallery/${imageName}`)
|
||||
|
||||
//// write to database
|
||||
Product.findById(req.body.product_id, (err, product) => {
|
||||
if (err) console.log(err)
|
||||
product.product_images.push({
|
||||
image: imageName,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
product.save()
|
||||
return res.json(product)
|
||||
})
|
||||
})
|
||||
|
||||
} else {
|
||||
return res.status(422).json({validation: {images: {image: {msg: 'عکس اجباری است.'}}}})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.deleteProductImage = [
|
||||
(req, res) => {
|
||||
Product.findOne({'product_images._id': req.params.imageID}, (err, product) => {
|
||||
if (err) return res.status(404).json(err)
|
||||
const productImage = product.product_images.id(req.params.imageID)
|
||||
fs.unlink(`./static/${productImage.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
productImage.remove()
|
||||
product.save(err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json(product)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
////////////////////////////////////////// products features controllers
|
||||
module.exports.createProductFeature = [
|
||||
[
|
||||
body('fa_name')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد'),
|
||||
body('en_name')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد'),
|
||||
body('de_name')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد'),
|
||||
body('tr_name')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد'),
|
||||
body('it_name')
|
||||
.notEmpty().withMessage('عنوان نباید خالی باشد'),
|
||||
|
||||
body('fa_value')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد'),
|
||||
body('en_value')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد'),
|
||||
body('tr_value')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد'),
|
||||
body('de_value')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد'),
|
||||
body('it_value')
|
||||
.notEmpty().withMessage('توضیحات نباید خالی باشد'),
|
||||
|
||||
body('product_id')
|
||||
.notEmpty().withMessage('مشخصات محصول را وارد کنید.')
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
return Product.findById(value)
|
||||
.then(product => {
|
||||
return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject('محصولی با این مشخصات وجود ندارد.')
|
||||
})
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: {features: errors.mapped()}})
|
||||
|
||||
const data = {
|
||||
fa: {
|
||||
name: req.body.fa_name,
|
||||
value: req.body.fa_value
|
||||
},
|
||||
en: {
|
||||
name: req.body.en_name,
|
||||
value: req.body.en_value
|
||||
},
|
||||
de: {
|
||||
name: req.body.de_name,
|
||||
value: req.body.de_value
|
||||
},
|
||||
tr: {
|
||||
name: req.body.tr_name,
|
||||
value: req.body.tr_value
|
||||
},
|
||||
it: {
|
||||
name: req.body.it_name,
|
||||
value: req.body.it_value
|
||||
},
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
Product.findById(req.body.product_id, (err, product) => {
|
||||
if (err) console.log(err)
|
||||
product.product_features.push(data)
|
||||
product.save()
|
||||
return res.json(product)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.deleteProductFeature = [
|
||||
(req, res) => {
|
||||
Product.findOne({'product_features._id': req.params.featureID}, (err, product) => {
|
||||
if (err) return res.status(500).json({message: err})
|
||||
product.product_features.id(req.params.featureID).remove()
|
||||
product.save()
|
||||
return res.json(product)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,195 @@
|
||||
const Slider = require('../models/Slider')
|
||||
const dateFormat = require('dateformat')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const jimp = require('jimp')
|
||||
const fs = require('fs')
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////// create
|
||||
module.exports.create = [
|
||||
[
|
||||
body('fa_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('en_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('de_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('tr_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('it_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
if (req.files) {
|
||||
let file = req.files.image
|
||||
let fileName = 'image_' + Date.now() + '.' + file.mimetype.split('/')[1]
|
||||
jimp.read(file.data)
|
||||
.then(img => {
|
||||
if (img.bitmap.width >= 1920 && img.bitmap.height >= 1080) {
|
||||
if (file.size / 1024 < 450) {
|
||||
file.mv(`./static/uploads/images/slider/${fileName}`, (err, img) => {
|
||||
const slider = new Slider({
|
||||
image: fileName,
|
||||
slider_details: {
|
||||
fa: {
|
||||
caption: req.body.fa_caption
|
||||
},
|
||||
en: {
|
||||
caption: req.body.en_caption
|
||||
},
|
||||
de: {
|
||||
caption: req.body.de_caption
|
||||
},
|
||||
tr: {
|
||||
caption: req.body.tr_caption
|
||||
},
|
||||
it: {
|
||||
caption: req.body.it_caption
|
||||
}
|
||||
},
|
||||
created_at: dateFormat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
})
|
||||
slider.save((err, data) => {
|
||||
if (err) return res.status(500).json({error: err})
|
||||
return res.json({message: 'اسلاید اضافه شد'})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'حجم تصویر نباید بیشتر از 450 کیلوبایت باشد'}}})
|
||||
}
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'ابعاد تصویر حداقل 1920*1080 پیکسل قابل قبول میباشد.'}}})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'عکس اجباری است.'}}})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////// get all
|
||||
module.exports.getAll = [
|
||||
(req, res) => {
|
||||
Slider.find({}, (err, slides) => {
|
||||
if (err) return res.status(404).json({error: err})
|
||||
return res.json(slides)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////// get one
|
||||
module.exports.getOne = [
|
||||
(req, res) => {
|
||||
Slider.findById(req.params.id, (err, slide) => {
|
||||
if (err) return res.status(404).json({error: 'no slide with this id.'})
|
||||
return res.json(slide)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////// update
|
||||
module.exports.update = [
|
||||
[
|
||||
body('fa_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('en_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('de_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('tr_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.'),
|
||||
|
||||
body('it_caption')
|
||||
.isLength({min: 10, max: 65}).withMessage('حداقل 10 کاراکتر و حداکثر 65 کاراکتر.')
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
slider_details: {
|
||||
fa: {
|
||||
caption: req.body.fa_caption
|
||||
},
|
||||
en: {
|
||||
caption: req.body.en_caption
|
||||
},
|
||||
de: {
|
||||
caption: req.body.de_caption
|
||||
},
|
||||
tr: {
|
||||
caption: req.body.tr_caption
|
||||
},
|
||||
it: {
|
||||
caption: req.body.it_caption
|
||||
}
|
||||
},
|
||||
updated_at: dateFormat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
if (req.files) {
|
||||
let file = req.files.image
|
||||
let fileName = 'image_' + Date.now() + '.' + file.mimetype.split('/')[1]
|
||||
|
||||
data.image = fileName
|
||||
|
||||
jimp.read(file.data)
|
||||
.then(img => {
|
||||
if (img.bitmap.width >= 1920 && img.bitmap.height >= 1080) {
|
||||
if (file.size / 1024 < 450) {
|
||||
file.mv(`./static/uploads/images/slider/${fileName}`, (err) => {
|
||||
if (err) console.log(err)
|
||||
|
||||
Slider.findByIdAndUpdate(req.params.id, data, (err, oldSlide) => {
|
||||
if (err) return res.status(500).json({error: err})
|
||||
fs.unlink(`./static/${oldSlide.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'اسلاید آپدیت شد.'})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'حجم تصویر نباید بیشتر از 450 کیلوبایت باشد'}}})
|
||||
}
|
||||
} else {
|
||||
return res.status(422).json({validation: {image: {msg: 'ابعاد تصویر حداقل 1920*1080 پیکسل قابل قبول میباشد.'}}})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
} else {
|
||||
Slider.findByIdAndUpdate(req.params.id, data, (err, oldSlide) => {
|
||||
if (err) return res.status(500).json({error: err})
|
||||
return res.json({message: 'اسلاید آپدیت شد.'})
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////// delete
|
||||
module.exports.delete = [
|
||||
(req, res) => {
|
||||
Slider.findByIdAndRemove(req.params.id, (err, data) => {
|
||||
if (err) return res.json({error: err})
|
||||
fs.unlink(`./static/${data.image}`, err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: 'اسلاید حذف شد'})
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,689 @@
|
||||
const User = require('../models/user/User')
|
||||
const v_m = require('../validation_messages')
|
||||
const {body, validationResult} = require('express-validator')
|
||||
const dateformat = require('dateformat')
|
||||
const bcrypt = require('bcryptjs')
|
||||
const crypto = require('crypto')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const config = require('../config')
|
||||
const nodemailer = require('nodemailer')
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// register
|
||||
module.exports.register = [
|
||||
[
|
||||
body('first_name')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.first_name
|
||||
})
|
||||
.bail()
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('last_name')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.last_name
|
||||
})
|
||||
.bail()
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('company_name')
|
||||
.if((value, {req}) => req.body.type === 'company')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.company_name
|
||||
}),
|
||||
|
||||
body('email_personal')
|
||||
.if((value, {req}) => req.body.type === 'personal')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email_personal
|
||||
}),
|
||||
|
||||
body('email_personal')
|
||||
.if(body('email_personal').notEmpty())
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
})
|
||||
.custom((value, {req}) => {
|
||||
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
|
||||
.then(user => {
|
||||
if (user) return Promise.reject(v_m[req.body.locale].duplicated.email)
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('email_company')
|
||||
.if((value, {req}) => req.body.type === 'company')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email_company
|
||||
})
|
||||
.bail()
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
})
|
||||
.custom((value, {req}) => {
|
||||
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
|
||||
.then(user => {
|
||||
if (user) return Promise.reject(v_m[req.body.locale].duplicated.email)
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('password')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
}),
|
||||
|
||||
body('phone_number')
|
||||
.isNumeric()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.phone_number
|
||||
}),
|
||||
|
||||
body('password_confirmation')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
})
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
|
||||
else return true
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {}
|
||||
data.first_name = req.body.first_name
|
||||
data.last_name = req.body.last_name
|
||||
data.type = req.body.type
|
||||
data.company_name = req.body.company_name
|
||||
data.email_personal = req.body.email_personal
|
||||
data.email_company = req.body.email_company
|
||||
data.fb_id_personal = req.body.fb_id_personal
|
||||
data.fb_id_company = req.body.fb_id_company
|
||||
data.ig_id_personal = req.body.ig_id_personal
|
||||
data.ig_id_company = req.body.ig_id_company
|
||||
data.skype_id_personal = req.body.skype_id_personal
|
||||
data.skype_id_company = req.body.skype_id_company
|
||||
data.phone_number = req.body.phone_number
|
||||
data.scope = 'user'
|
||||
data.created_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
|
||||
|
||||
// generate activation key
|
||||
let confirmation_key
|
||||
crypto.randomBytes(20, async (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
confirmation_key = hash.toString('hex')
|
||||
data.confirmation_key = confirmation_key
|
||||
|
||||
let transporter = nodemailer.createTransport({
|
||||
host: "www.rubynaturalco.com",
|
||||
port: 587,
|
||||
secure: false, // true for 465, false for other ports
|
||||
auth: {
|
||||
user: 'recovery@rubynaturalco.com',
|
||||
pass: 'jd-m2?3ao?b('
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
})
|
||||
|
||||
// send mail with defined transport object
|
||||
let info = await transporter.sendMail({
|
||||
from: '"Hima Co." <recovery@rubynaturalco.com>', // sender address
|
||||
to: req.body.type === 'personal' ? req.body.email_personal : req.body.email_company, // list of receivers
|
||||
subject: "Activation Link",
|
||||
text: 'Active your account',
|
||||
html: `
|
||||
<h1>You just registered an account on <b style="color: #784fae;">Hima Website</b></h1>
|
||||
<p>to activate your account click link below:</p>
|
||||
<a href="https://www.rubynaturalco.com/en/account/activation/${confirmation_key}"
|
||||
target="_blank"
|
||||
style="display: inline-block;font-family: sans-serif;padding: 15px;background: #784fae;color: #fff;border-radius: 5px;margin-top: 20px;">Active Account</a>
|
||||
`
|
||||
})
|
||||
|
||||
// hash user password and done
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(req.body.password, salt, (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
data.password = hash
|
||||
|
||||
const user = new User(data)
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// active user
|
||||
module.exports.activation = [
|
||||
(req, res) => {
|
||||
User.findOne({confirmation_key: req.params.key})
|
||||
.then(user => {
|
||||
if (user) {
|
||||
user.confirmation_key = null
|
||||
user.confirmed = true
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: v_m[req.body.locale].response.success_activation})
|
||||
})
|
||||
} else {
|
||||
return res.status(404).json({message: v_m[req.body.locale].response.expired_activation_link})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// login
|
||||
module.exports.login = [
|
||||
[
|
||||
body('email')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email
|
||||
})
|
||||
.custom((value, {req}) => {
|
||||
return User.findOne({$or: [{email_personal: value}, {email_company: value}]})
|
||||
.then(user => {
|
||||
if (!user) return Promise.reject(v_m[req.body.locale].not_found.user_id)
|
||||
else return true
|
||||
})
|
||||
}),
|
||||
|
||||
body('password')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.password
|
||||
}),
|
||||
|
||||
body('remember_me')
|
||||
.exists()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.remember_me
|
||||
})
|
||||
.bail()
|
||||
.isBoolean()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.boolean
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
|
||||
User.findOne({$or: [{email_personal: req.body.email}, {email_company: req.body.email}]}, (err, user) => {
|
||||
if (err) console.log(err)
|
||||
if (!user.confirmed) return res.status(401).json({message: v_m[req.body.locale].response.email_not_confirmed})
|
||||
bcrypt.compare(req.body.password, user.password, (err, isMatch) => {
|
||||
if (err) console.log(err)
|
||||
if (!isMatch) return res.status(422).json({validation: {password: {msg: v_m[req.body.locale].not_found.password}}})
|
||||
let token
|
||||
if (req.body.remember_me) token = jwt.sign({_id: user._id}, config.secretKey)
|
||||
else token = jwt.sign({_id: user._id}, config.secretKey, {expiresIn: '1h'})
|
||||
|
||||
user.token = token
|
||||
user.reset_pass_key = null
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({token: token})
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// logout
|
||||
module.exports.logout = [
|
||||
(req, res) => {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
User.findOneAndUpdate({token: token}, {token: null}, (err, oldData) => {
|
||||
if (err) console.log(err)
|
||||
if (oldData) return res.json({message: v_m['en'].response.logged_out})
|
||||
return res.status(401).json({message: v_m['en'].response.not_logged_in})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: v_m['en'].response.not_logged_in})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// get user
|
||||
module.exports.getUser = [
|
||||
config.isUser,
|
||||
(req, res) => {
|
||||
const token = req.headers.authorization
|
||||
if (token) {
|
||||
jwt.verify(token, config.secretKey, (err, decoded) => {
|
||||
if (err) return res.status(401).json({message: v_m['en'].response.unauthenticated})
|
||||
User.findById(decoded._id).select('-password -reset_pass_key -token -confirmed -confirmation_key').exec((err, data) => {
|
||||
if (err) console.log(err)
|
||||
return res.json({user: data})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(401).json({message: v_m['en'].response.unauthenticated})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// reset password key generator
|
||||
module.exports.resetPassKey = [
|
||||
[
|
||||
body('email')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email
|
||||
})
|
||||
.bail()
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
User.findOne({$or: [{email_personal: req.body.email}, {email_company: req.body.email}]})
|
||||
.then(user => {
|
||||
if (user) {
|
||||
let pass_token
|
||||
crypto.randomBytes(20, async (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
pass_token = hash.toString('hex')
|
||||
user.reset_pass_key = pass_token
|
||||
await user.save(err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
|
||||
let transporter = nodemailer.createTransport({
|
||||
host: "www.rubynaturalco.com",
|
||||
port: 587,
|
||||
secure: false, // true for 465, false for other ports
|
||||
auth: {
|
||||
user: 'recovery@rubynaturalco.com',
|
||||
pass: 'jd-m2?3ao?b('
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
})
|
||||
|
||||
// send mail with defined transport object
|
||||
let info = await transporter.sendMail({
|
||||
from: '"Hima Co." <recovery@rubynaturalco.com>', // sender address
|
||||
to: req.body.email, // list of receivers
|
||||
subject: "Reset Password Link",
|
||||
text: 'Reset your password',
|
||||
html: `
|
||||
<h1>You asked to reset your account password on <b style="color: #784fae;">Hima Website</b></h1>
|
||||
<p>to reset your password click on link blow, then enter new password:</p>
|
||||
<a href="https://www.rubynaturalco.com/en/account/new-password/${pass_token}"
|
||||
target="_blank"
|
||||
style="display: inline-block;font-family: sans-serif;padding: 15px;background: #784fae;color: #fff;border-radius: 5px;margin-top: 20px;">Reset Password</a>
|
||||
`
|
||||
})
|
||||
|
||||
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
|
||||
return res.json({message: v_m[req.body.locale].response.recovery_link})
|
||||
})
|
||||
} else {
|
||||
return res.status(404).json({message: v_m[req.body.locale].not_found.user_id})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// set new password
|
||||
module.exports.setNewPass = [
|
||||
[
|
||||
body('password')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
})
|
||||
,
|
||||
|
||||
body('password_confirmation')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
})
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
|
||||
else return true
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
User.findOne({reset_pass_key: req.params.key})
|
||||
.then(user => {
|
||||
if (user) {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(req.body.password, salt, (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
user.password = hash
|
||||
user.reset_pass_key = null
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
return res.status(404).json({message: v_m[req.body.locale].response.expired_reset_link})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(500).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// update user
|
||||
module.exports.updateUser = [
|
||||
[
|
||||
body('first_name')
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('last_name')
|
||||
.isLength({min: 2})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min2
|
||||
}),
|
||||
|
||||
body('email_personal')
|
||||
.if((value, {req}) => req.body.type === 'personal')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email_personal
|
||||
}),
|
||||
|
||||
body('email_personal')
|
||||
.if(body('email_personal').notEmpty())
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
}),
|
||||
|
||||
body('phone_number')
|
||||
.isNumeric()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.phone_number
|
||||
}),
|
||||
|
||||
body('email_company')
|
||||
.if((value, {req}) => req.body.type === 'company')
|
||||
.notEmpty()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].required.email_company
|
||||
})
|
||||
.bail()
|
||||
.isEmail()
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].format.email
|
||||
}),
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const token = req.headers.authorization
|
||||
const data = {}
|
||||
data.first_name = req.body.first_name
|
||||
data.last_name = req.body.last_name
|
||||
data.email_personal = req.body.email_personal
|
||||
data.fb_id_personal = req.body.fb_id_personal
|
||||
data.ig_id_personal = req.body.ig_id_personal
|
||||
data.skype_id_personal = req.body.skype_id_personal
|
||||
data.phone_number = req.body.phone_number
|
||||
data.updated_at = dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
|
||||
if (req.body.type === 'company') {
|
||||
data.skype_id_company = req.body.skype_id_company
|
||||
data.ig_id_company = req.body.ig_id_company
|
||||
data.fb_id_company = req.body.fb_id_company
|
||||
data.email_company = req.body.email_company
|
||||
data.company_name = req.body.company_name
|
||||
}
|
||||
User.findOneAndUpdate({token: token}, data)
|
||||
.then(user => {
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(401).json({message: v_m[req.body.locale].response.unauthenticated})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// update user password
|
||||
module.exports.updateUserPassword = [
|
||||
[
|
||||
body('password')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
}),
|
||||
|
||||
body('password_confirmation')
|
||||
.isLength({min: 4})
|
||||
.withMessage((value, {req}) => {
|
||||
return v_m[req.body.locale].min_char.min4
|
||||
})
|
||||
.bail()
|
||||
.custom((value, {req}) => {
|
||||
if (value !== req.body.password) return Promise.reject(v_m[req.body.locale].required.password_confirmation)
|
||||
else return true
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const token = req.headers.authorization
|
||||
User.findOne({token: token})
|
||||
.then(user => {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
if (err) console.log(err)
|
||||
bcrypt.hash(req.body.password, salt, (err, hash) => {
|
||||
if (err) console.log(err)
|
||||
user.password = hash
|
||||
user.token = null
|
||||
user.save(err => {
|
||||
if (err) console.log(err)
|
||||
return res.json({message: v_m[req.body.locale].response.success_save})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// addresses
|
||||
module.exports.addAdress = [
|
||||
[
|
||||
body('user_id')
|
||||
.custom((value, {req}) => {
|
||||
return User.findById(value)
|
||||
.then(user => {
|
||||
return true
|
||||
})
|
||||
.catch(err => {
|
||||
return Promise.reject(v_m[req.body.locale].not_found.user_id)
|
||||
})
|
||||
}),
|
||||
|
||||
body('country')
|
||||
.if(body('country').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.country)
|
||||
}),
|
||||
|
||||
body('province')
|
||||
.if(body('province').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.province)
|
||||
}),
|
||||
|
||||
body('city')
|
||||
.if(body('city').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.city)
|
||||
}),
|
||||
|
||||
body('address')
|
||||
.if(body('address').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.address)
|
||||
}),
|
||||
|
||||
body('postal_code')
|
||||
.if(body('postal_code').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.postal_code)
|
||||
}),
|
||||
|
||||
body('plaque')
|
||||
.if(body('plaque').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.plaque)
|
||||
}),
|
||||
|
||||
body('receiver_first_name')
|
||||
.if(body('receiver_first_name').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.receiver_first_name)
|
||||
}),
|
||||
|
||||
body('receiver_last_name')
|
||||
.if(body('receiver_last_name').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.receiver_last_name)
|
||||
}),
|
||||
|
||||
body('receiver_mobile')
|
||||
.if(body('receiver_mobile').isEmpty())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].required.receiver_mobile)
|
||||
}),
|
||||
|
||||
body('receiver_mobile')
|
||||
.if(body('receiver_mobile').notEmpty())
|
||||
.if(body('receiver_mobile').not().isNumeric())
|
||||
.custom((value, {req}) => {
|
||||
return Promise.reject(v_m[req.body.locale].format.phone_number)
|
||||
})
|
||||
],
|
||||
(req, res) => {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()})
|
||||
|
||||
const data = {
|
||||
country: req.body.country,
|
||||
province: req.body.province,
|
||||
city: req.body.city,
|
||||
address: req.body.address,
|
||||
postal_code: req.body.postal_code,
|
||||
plaque: req.body.plaque,
|
||||
block_number: req.body.block_number,
|
||||
receiver_first_name: req.body.receiver_first_name,
|
||||
receiver_last_name: req.body.receiver_last_name,
|
||||
receiver_mobile: req.body.receiver_mobile,
|
||||
created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss')
|
||||
}
|
||||
|
||||
User.findById(req.body.user_id)
|
||||
.then(user => {
|
||||
user.addresses.push(data)
|
||||
user.save()
|
||||
return res.json(user.addresses)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getAddresses = [
|
||||
(req, res) => {
|
||||
User.findById(req.params.user_id)
|
||||
.then(user => {
|
||||
return res.json(user.addresses)
|
||||
})
|
||||
.catch(err => {
|
||||
return res.status(404).json({message: v_m['en'].not_found.user_id})
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.deleteAddress = [
|
||||
(req, res) => {
|
||||
User.findOne({'addresses._id': req.params.address_id})
|
||||
.then(user => {
|
||||
user.addresses.id(req.params.address_id).remove()
|
||||
user.save()
|
||||
return res.json({message: v_m['en'].response.success_remove})
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
/////////////////////////////////////////////////////////////////////// get list of users by admin
|
||||
module.exports.getAllUsers = [
|
||||
(req, res) => {
|
||||
User.find({confirmed: true}).select('-token -password -scope -reset_pass_key -confirmed -confirmation_key').exec((err, users) => {
|
||||
if (err) console.log(err)
|
||||
return res.json(users)
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
module.exports.getOneUser = [
|
||||
(req, res) => {
|
||||
User.findById(req.params.user_id).select('-token -password -scope -reset_pass_key -confirmed -confirmation_key').exec((err, user) => {
|
||||
if (err) return res.status(404).json(err)
|
||||
return res.json(user)
|
||||
})
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,62 @@
|
||||
const User = require('./models/user/User')
|
||||
const Cart_Item = require('./models/user/Cart_item')
|
||||
|
||||
const minute = 1000 * 60
|
||||
const hour = minute * 60
|
||||
const day = hour * 24
|
||||
|
||||
module.exports = () => {
|
||||
// check users for activation
|
||||
setInterval(() => {
|
||||
User.find({confirmed: false})
|
||||
.then(users => {
|
||||
if (users.length) {
|
||||
///////////////////////
|
||||
users.forEach((item, index) => {
|
||||
// item time and timeout
|
||||
const itemTime = Date.parse(item.created_at)
|
||||
const timeout = itemTime + day
|
||||
////////////////////////////
|
||||
if (Date.now() >= timeout) {
|
||||
item.remove()
|
||||
}
|
||||
if (index === users.length - 1) {
|
||||
console.log('Computing Done.')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('Computing Done.')
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}, hour)
|
||||
|
||||
// check cart items
|
||||
setInterval(() => {
|
||||
Cart_Item.find({})
|
||||
.then(cart_items => {
|
||||
if (cart_items.length) {
|
||||
///////////////////////
|
||||
cart_items.forEach((item, index) => {
|
||||
// item time and timeout
|
||||
const itemTime = Date.parse(item.created_at)
|
||||
const timeout = itemTime + (day * 7)
|
||||
////////////////////////////
|
||||
if (Date.now() >= timeout) {
|
||||
item.remove()
|
||||
}
|
||||
if (index === cart_items.length - 1) {
|
||||
console.log('Computing Done.')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('Computing Done.')
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}, day)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
const mongoose = require('mongoose');
|
||||
// mongodb database connection string. change it as per your needs. here "mydb" is the name of the database. You don't need to create DB from mongodb terminal. mongoose create the db automatically.
|
||||
mongoose.connect('mongodb://localhost:27017/hima', {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
useFindAndModify: false,
|
||||
useCreateIndex: true
|
||||
});
|
||||
var db = mongoose.connection;
|
||||
db.on('error', console.error.bind(console, 'connection error:'));
|
||||
db.once('open', function callback() {
|
||||
console.log("MongoDB Connected...");
|
||||
});
|
||||
|
||||
module.exports = db
|
||||
@@ -0,0 +1,34 @@
|
||||
const express = require('express')
|
||||
const db = require('./db')
|
||||
const fileUpload = require('express-fileupload')
|
||||
const config = require('./config')
|
||||
const cron_jobs = require('./cron_jobs')
|
||||
|
||||
// Create express instnace
|
||||
const app = express()
|
||||
|
||||
// Init body-parser options (inbuilt with express)
|
||||
app.use(express.json())
|
||||
app.use(express.urlencoded({extended: true}))
|
||||
app.use(fileUpload())
|
||||
|
||||
// Require & Import API routes
|
||||
const Private = require('./routes/private')
|
||||
const Public = require('./routes/public')
|
||||
const user = require('./routes/user')
|
||||
const auth = require('./routes/auth')
|
||||
|
||||
// Use API Routes
|
||||
app.use('/private', config.isAdmin, Private)
|
||||
app.use('/user', config.isUser, user)
|
||||
app.use('/auth', auth)
|
||||
app.use('/public', Public)
|
||||
|
||||
// add cron jobs checker
|
||||
cron_jobs()
|
||||
|
||||
// Export the server middleware
|
||||
module.exports = {
|
||||
path: '/api',
|
||||
handler: app
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function image(img) {
|
||||
return '/uploads/images/about/' + img
|
||||
}
|
||||
|
||||
const AboutPageSchema = mongoose.Schema({
|
||||
aboutPage_details: {
|
||||
fa: {
|
||||
page_title: String,
|
||||
s1_title: String,
|
||||
s1_caption: String,
|
||||
s2_title: String,
|
||||
s2_caption: String,
|
||||
s2_imageCaption: String,
|
||||
s3_title: String,
|
||||
s3_caption: String,
|
||||
s3_imageCaption: String,
|
||||
s4_text: String,
|
||||
last_section_title: String,
|
||||
last_section_text: String
|
||||
},
|
||||
en: {
|
||||
page_title: String,
|
||||
s1_title: String,
|
||||
s1_caption: String,
|
||||
s2_title: String,
|
||||
s2_caption: String,
|
||||
s2_imageCaption: String,
|
||||
s3_title: String,
|
||||
s3_caption: String,
|
||||
s3_imageCaption: String,
|
||||
s4_text: String,
|
||||
last_section_title: String,
|
||||
last_section_text: String
|
||||
},
|
||||
de: {
|
||||
page_title: String,
|
||||
s1_title: String,
|
||||
s1_caption: String,
|
||||
s2_title: String,
|
||||
s2_caption: String,
|
||||
s2_imageCaption: String,
|
||||
s3_title: String,
|
||||
s3_caption: String,
|
||||
s3_imageCaption: String,
|
||||
s4_text: String,
|
||||
last_section_title: String,
|
||||
last_section_text: String
|
||||
},
|
||||
tr: {
|
||||
page_title: String,
|
||||
s1_title: String,
|
||||
s1_caption: String,
|
||||
s2_title: String,
|
||||
s2_caption: String,
|
||||
s2_imageCaption: String,
|
||||
s3_title: String,
|
||||
s3_caption: String,
|
||||
s3_imageCaption: String,
|
||||
s4_text: String,
|
||||
last_section_title: String,
|
||||
last_section_text: String
|
||||
},
|
||||
it: {
|
||||
page_title: String,
|
||||
s1_title: String,
|
||||
s1_caption: String,
|
||||
s2_title: String,
|
||||
s2_caption: String,
|
||||
s2_imageCaption: String,
|
||||
s3_title: String,
|
||||
s3_caption: String,
|
||||
s3_imageCaption: String,
|
||||
s4_text: String,
|
||||
last_section_title: String,
|
||||
last_section_text: String
|
||||
}
|
||||
},
|
||||
page_hero: {type: String, get: image},
|
||||
s2_image: {type: String, get: image},
|
||||
s3_image: {type: String, get: image},
|
||||
last_section_image: {type: String, get: image},
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
|
||||
module.exports = mongoose.model('AboutPageContent', AboutPageSchema)
|
||||
@@ -0,0 +1,13 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const BroadcastSchema = mongoose.Schema({
|
||||
title: String,
|
||||
message: String,
|
||||
read: Array,
|
||||
locale: String,
|
||||
admin_id: String,
|
||||
created_at: String
|
||||
})
|
||||
|
||||
|
||||
module.exports = mongoose.model('Broadcast', BroadcastSchema)
|
||||
@@ -0,0 +1,14 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const ContactPageMessageSchema = mongoose.Schema({
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
phone_number: String,
|
||||
email: String,
|
||||
message: String,
|
||||
user_id: String,
|
||||
read: {type: Boolean, default: false},
|
||||
created_at: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('ContactPageMessage', ContactPageMessageSchema)
|
||||
@@ -0,0 +1,19 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function image(file) {
|
||||
return `/uploads/images/gallery/${file}`
|
||||
}
|
||||
|
||||
const gallerySchema = mongoose.Schema({
|
||||
image: {type: String, get: image},
|
||||
created_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
gallerySchema.virtual('thumb').get(function () {
|
||||
return '/uploads/images/gallery/thumb/thumb_' + this.image.split('gallery/')[1]
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Gallery', gallerySchema)
|
||||
@@ -0,0 +1,33 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function image(img) {
|
||||
return '/uploads/images/slider/' + img
|
||||
}
|
||||
|
||||
const SliderSchema = mongoose.Schema({
|
||||
image: {type: String, get: image},
|
||||
slider_details: {
|
||||
fa: {
|
||||
caption: String
|
||||
},
|
||||
en: {
|
||||
caption: String
|
||||
},
|
||||
de: {
|
||||
caption: String
|
||||
},
|
||||
tr: {
|
||||
caption: String
|
||||
},
|
||||
it: {
|
||||
caption: String
|
||||
}
|
||||
},
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Slider', SliderSchema)
|
||||
@@ -0,0 +1,14 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const AdminSchema = mongoose.Schema({
|
||||
name: String,
|
||||
username: String,
|
||||
password: String,
|
||||
roles: Array,
|
||||
created_at: String,
|
||||
updated_at: String,
|
||||
scope: String,
|
||||
token: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Admin', AdminSchema)
|
||||
@@ -0,0 +1,25 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const BlogCategorySchema = mongoose.Schema({
|
||||
blogCategory_details: {
|
||||
fa: {
|
||||
name: String
|
||||
},
|
||||
en: {
|
||||
name: String
|
||||
},
|
||||
de: {
|
||||
name: String
|
||||
},
|
||||
tr: {
|
||||
name: String
|
||||
},
|
||||
it: {
|
||||
name: String
|
||||
}
|
||||
},
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('BlogCategory', BlogCategorySchema)
|
||||
@@ -0,0 +1,49 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function cover(img) {
|
||||
return '/uploads/images/blog/' + img
|
||||
}
|
||||
|
||||
const BlogPostSchema = mongoose.Schema({
|
||||
cover: {type: String, get: cover},
|
||||
published: {type: Boolean, default: true},
|
||||
category: String,
|
||||
post_details: {
|
||||
fa: {
|
||||
title: String,
|
||||
description: String,
|
||||
short_description: String
|
||||
},
|
||||
en: {
|
||||
title: String,
|
||||
description: String,
|
||||
short_description: String
|
||||
},
|
||||
de: {
|
||||
title: String,
|
||||
description: String,
|
||||
short_description: String
|
||||
},
|
||||
tr: {
|
||||
title: String,
|
||||
description: String,
|
||||
short_description: String
|
||||
},
|
||||
it: {
|
||||
title: String,
|
||||
description: String,
|
||||
short_description: String
|
||||
}
|
||||
},
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
BlogPostSchema.virtual('thumb').get(function () {
|
||||
return '/uploads/images/blog/thumb_' + this.cover.split('blog/')[1]
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('BlogPost', BlogPostSchema)
|
||||
@@ -0,0 +1,100 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function productImage(img) {
|
||||
return '/uploads/images/products/' + img
|
||||
}
|
||||
|
||||
function ProductImageGallery(img) {
|
||||
return '/uploads/images/products/gallery/' + img
|
||||
}
|
||||
|
||||
|
||||
const ProductFeatureSchema = mongoose.Schema({
|
||||
fa: {
|
||||
name: String,
|
||||
value: String
|
||||
},
|
||||
en: {
|
||||
name: String,
|
||||
value: String
|
||||
},
|
||||
de: {
|
||||
name: String,
|
||||
value: String
|
||||
},
|
||||
tr: {
|
||||
name: String,
|
||||
value: String
|
||||
},
|
||||
it: {
|
||||
name: String,
|
||||
value: String
|
||||
},
|
||||
created_at: String
|
||||
})
|
||||
|
||||
const ProductImageSchema = mongoose.Schema({
|
||||
image: {type: String, get: ProductImageGallery},
|
||||
created_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
const ProductSchema = mongoose.Schema({
|
||||
image: {type: String, get: productImage},
|
||||
stock: Number,
|
||||
category: String,
|
||||
product_details: {
|
||||
fa: {
|
||||
name: String,
|
||||
description: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
en: {
|
||||
name: String,
|
||||
description: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
de: {
|
||||
name: String,
|
||||
description: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
it: {
|
||||
name: String,
|
||||
description: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
tr: {
|
||||
name: String,
|
||||
description: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
product_features: [ProductFeatureSchema],
|
||||
product_images: [ProductImageSchema],
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
|
||||
module.exports = mongoose.model('Product', ProductSchema)
|
||||
@@ -0,0 +1,39 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
function image(img) {
|
||||
return '/uploads/images/products/category/' + img
|
||||
}
|
||||
|
||||
const ProductCategorySchema = mongoose.Schema({
|
||||
image: {type: String, get: image},
|
||||
cover: {type: String, get: image},
|
||||
category_details: {
|
||||
fa: {
|
||||
name: String,
|
||||
caption: String
|
||||
},
|
||||
en: {
|
||||
name: String,
|
||||
caption: String
|
||||
},
|
||||
de: {
|
||||
name: String,
|
||||
caption: String
|
||||
},
|
||||
tr: {
|
||||
name: String,
|
||||
caption: String
|
||||
},
|
||||
it: {
|
||||
name: String,
|
||||
caption: String
|
||||
}
|
||||
},
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
}, {
|
||||
toObject: {getters: true},
|
||||
toJSON: {getters: true}
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('ProductCategory', ProductCategorySchema)
|
||||
@@ -0,0 +1,11 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const Cart_ItemSchema = mongoose.Schema({
|
||||
user_id: String,
|
||||
product_id: String,
|
||||
quantity: String,
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Cart_Item', Cart_ItemSchema)
|
||||
@@ -0,0 +1,30 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const StatusSchema = mongoose.Schema({
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['incomplete','processing', 'packing', 'sent','delivered'],
|
||||
default: 'processing'
|
||||
},
|
||||
created_at: String
|
||||
})
|
||||
|
||||
const Order_itemsSchema = mongoose.Schema({
|
||||
product_id: String,
|
||||
quantity: Number,
|
||||
price: Number,
|
||||
price_unit: String,
|
||||
created_at: String
|
||||
})
|
||||
|
||||
const OrderSchema = mongoose.Schema({
|
||||
user_id: String,
|
||||
number: Number,
|
||||
address: Object,
|
||||
statuses: [StatusSchema],
|
||||
order_items: [Order_itemsSchema],
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Order', OrderSchema)
|
||||
@@ -0,0 +1,43 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const AddressSchema = mongoose.Schema({
|
||||
country: String,
|
||||
province: String,
|
||||
city: String,
|
||||
address: String,
|
||||
postal_code: String,
|
||||
plaque: String,
|
||||
block_number: String,
|
||||
receiver_first_name: String,
|
||||
receiver_last_name: String,
|
||||
receiver_mobile: String,
|
||||
created_at: String
|
||||
})
|
||||
|
||||
|
||||
const UserSchema = mongoose.Schema({
|
||||
first_name: String,
|
||||
last_name: String,
|
||||
type: {type: String, enum: ['personal', 'company'], default: 'personal'},
|
||||
company_name: String,
|
||||
email_personal: String,
|
||||
email_company: String,
|
||||
fb_id_personal: String,
|
||||
fb_id_company: String,
|
||||
ig_id_personal: String,
|
||||
ig_id_company: String,
|
||||
skype_id_personal: String,
|
||||
skype_id_company: String,
|
||||
addresses: [AddressSchema],
|
||||
phone_number: String,
|
||||
password: String,
|
||||
confirmed: {type: Boolean, default: false},
|
||||
confirmation_key: String,
|
||||
scope: String,
|
||||
token: String,
|
||||
reset_pass_key: String,
|
||||
created_at: String,
|
||||
updated_at: String
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('User', UserSchema)
|
||||
@@ -0,0 +1,21 @@
|
||||
const {Router} = require('express')
|
||||
const router = Router()
|
||||
const adminController = require('../controllers/adminController')
|
||||
const userController = require('../controllers/userController')
|
||||
|
||||
////////////////////// admin routes
|
||||
router.post('/admin/register', adminController.register)
|
||||
|
||||
router.post('/admin/login', adminController.login)
|
||||
router.post('/admin/logout', adminController.logout)
|
||||
router.get('/admin/user', adminController.getUser)
|
||||
|
||||
|
||||
////////////////////// user routes
|
||||
router.post('/user/register', userController.register)
|
||||
|
||||
router.post('/user/login', userController.login)
|
||||
router.post('/user/logout', userController.logout)
|
||||
router.get('/user/user', userController.getUser)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,76 @@
|
||||
const {Router} = require('express')
|
||||
const router = Router()
|
||||
/////////////////////////////////////////////////////////// controllers
|
||||
const sliderController = require('../controllers/sliderController')
|
||||
const aboutPageContent_controller = require('../controllers/aboutPageContent_controller')
|
||||
const productController = require('../controllers/productController')
|
||||
const productCategoryController = require('../controllers/productCategoryController')
|
||||
const blogCategoryController = require('../controllers/blogCategoryController')
|
||||
const blogPostController = require('../controllers/blogPostController')
|
||||
const userController = require('../controllers/userController')
|
||||
const orderController = require('../controllers/orderController')
|
||||
const galleryController = require('../controllers/galleryController')
|
||||
const contactPageController = require('../controllers/contactPageController')
|
||||
const broadcastController = require('../controllers/broadcastController')
|
||||
|
||||
/////////////////////////////////////////////////////////// routes
|
||||
//////////////// slider
|
||||
router.post('/slider', sliderController.create)
|
||||
router.put('/slider/:id', sliderController.update)
|
||||
router.delete('/slider/:id', sliderController.delete)
|
||||
|
||||
//////////////// about page content
|
||||
router.post('/aboutPage', aboutPageContent_controller.create)
|
||||
|
||||
//////////////// blog categories
|
||||
router.post('/blogCategories', blogCategoryController.create)
|
||||
router.put('/blogCategories/:id', blogCategoryController.update)
|
||||
router.delete('/blogCategories/:id', blogCategoryController.delete)
|
||||
|
||||
//////////////// blog posts
|
||||
router.post('/blog', blogPostController.create)
|
||||
router.put('/blog/:id', blogPostController.update)
|
||||
router.delete('/blog/:id', blogPostController.delete)
|
||||
|
||||
//////////////// product categories
|
||||
router.post('/productCategories', productCategoryController.create)
|
||||
router.put('/productCategories/:id', productCategoryController.update)
|
||||
router.delete('/productCategories/:id', productCategoryController.delete)
|
||||
|
||||
//////////////// products
|
||||
router.post('/products', productController.createProduct)
|
||||
router.put('/products/:id', productController.updateProduct)
|
||||
router.delete('/products/:id', productController.deleteProduct)
|
||||
|
||||
// product image
|
||||
router.post('/productImage', productController.createProductImage)
|
||||
router.delete('/productImage/:imageID', productController.deleteProductImage)
|
||||
|
||||
// product feature
|
||||
router.post('/productFeature', productController.createProductFeature)
|
||||
router.delete('/productFeature/:featureID', productController.deleteProductFeature)
|
||||
|
||||
//////////////// users
|
||||
router.get('/customers', userController.getAllUsers)
|
||||
router.get('/customers/:user_id', userController.getOneUser)
|
||||
|
||||
// user orders
|
||||
router.get('/orders', orderController.getAllOrders)
|
||||
router.get('/orders/:user_id', orderController.getOrders)
|
||||
router.get('/order/:order_id', orderController.getOneOrder)
|
||||
router.post('/addStatusToOrder/:order_id', orderController.addStatusToOrder)
|
||||
|
||||
//////////////// gallery
|
||||
router.post('/gallery', galleryController.create)
|
||||
router.delete('/gallery/:id', galleryController.delete)
|
||||
|
||||
//////////////// contact us
|
||||
router.get('/contact', contactPageController.getAll)
|
||||
router.get('/contact/:id', contactPageController.getOne)
|
||||
|
||||
//////////////// broadcast
|
||||
router.post('/broadcast', broadcastController.create)
|
||||
router.get('/broadcast', broadcastController.getAll)
|
||||
router.delete('/broadcast/:id', broadcastController.delete)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,62 @@
|
||||
const {Router} = require('express')
|
||||
const router = Router()
|
||||
|
||||
/////////////////////////////////////////////////////////// controllers
|
||||
const sliderController = require('../controllers/sliderController')
|
||||
const localeController = require('../controllers/localeController')
|
||||
const aboutPageContent_controller = require('../controllers/aboutPageContent_controller')
|
||||
const productController = require('../controllers/productController')
|
||||
const productCategoryController = require('../controllers/productCategoryController')
|
||||
const blogCategoryController = require('../controllers/blogCategoryController')
|
||||
const blogPostController = require('../controllers/blogPostController')
|
||||
const galleryController = require('../controllers/galleryController')
|
||||
const contactPageController = require('../controllers/contactPageController')
|
||||
const userController = require('../controllers/userController')
|
||||
|
||||
/////////////////////////////////////////////////////////// routes
|
||||
|
||||
//////////////// locale
|
||||
router.get('/locale', localeController.get)
|
||||
|
||||
//////////////// active user account
|
||||
router.post('/activeUser/:key', userController.activation)
|
||||
|
||||
//////////////// reset pass
|
||||
router.post('/resetPass', userController.resetPassKey)
|
||||
router.post('/setNewPass/:key', userController.setNewPass)
|
||||
|
||||
//////////////// slider
|
||||
router.get('/slider', sliderController.getAll)
|
||||
router.get('/slider/:id', sliderController.getOne)
|
||||
|
||||
//////////////// about page content
|
||||
router.get('/aboutPage', aboutPageContent_controller.get)
|
||||
|
||||
//////////////// blog category
|
||||
router.get('/blogCategories', blogCategoryController.getAll)
|
||||
router.get('/blogCategories/:id', blogCategoryController.getOne)
|
||||
|
||||
//////////////// blog posts
|
||||
router.get('/blog', blogPostController.getAll)
|
||||
router.get('/blog/:id', blogPostController.getOne)
|
||||
|
||||
//////////////// product categories
|
||||
router.get('/productCategories', productCategoryController.getAll)
|
||||
router.get('/productCategories/:id', productCategoryController.getOne)
|
||||
|
||||
//////////////// products
|
||||
router.get('/products/:category', productController.getAllProductsByCategory)
|
||||
router.get('/products/', productController.getAllProducts)
|
||||
router.get('/product/:id', productController.getOneProduct)
|
||||
|
||||
//////////////// gallery
|
||||
router.get('/gallery', galleryController.getAll)
|
||||
router.get('/gallery/:id', galleryController.getOne)
|
||||
|
||||
// //////////////// subscribers
|
||||
// router.post('/subscribers',subscribersController.create)
|
||||
|
||||
//////////////// contact us
|
||||
router.post('/contact', contactPageController.create)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,33 @@
|
||||
const {Router} = require('express')
|
||||
const router = Router()
|
||||
|
||||
const orderController = require('../controllers/orderController')
|
||||
const userController = require('../controllers/userController')
|
||||
const broadcastController = require('../controllers/broadcastController')
|
||||
|
||||
// cart
|
||||
router.post('/addToCart', orderController.addToCart)
|
||||
router.put('/updateCart/:item_id', orderController.updateCart)
|
||||
router.get('/cartItems/:user_id', orderController.getCartItems)
|
||||
router.delete('/deleteItem/:item_id', orderController.deleteFromCart)
|
||||
|
||||
// order
|
||||
router.post('/addOrder', orderController.addOrder)
|
||||
router.post('/addAddressToOrder/:order_id', orderController.addAddressToOrder)
|
||||
router.get('/orders/:user_id', orderController.getOrders)
|
||||
router.get('/order/:order_id', orderController.getOneOrder)
|
||||
|
||||
// address
|
||||
router.post('/addAddress', userController.addAdress)
|
||||
router.delete('/addresses/:address_id', userController.deleteAddress)
|
||||
router.get('/addresses/:user_id', userController.getAddresses)
|
||||
|
||||
// update profile
|
||||
router.put('/profile', userController.updateUser)
|
||||
router.post('/password', userController.updateUserPassword)
|
||||
|
||||
// broadcast
|
||||
router.get('/broadcast', broadcastController.getAll)
|
||||
router.post('/broadcast/:id', broadcastController.getOne)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,532 @@
|
||||
module.exports = {
|
||||
fa: {
|
||||
required: {
|
||||
// developer validations
|
||||
remember_me: 'پارامتر remember_me الزامی است',
|
||||
// registration validations
|
||||
first_name: 'نام را وارد کنید',
|
||||
last_name: 'نام خانوادگی را وارد کنید',
|
||||
email: 'ایمیل را وارد کنید',
|
||||
email_personal: 'ایمیل شخصی الزامی است',
|
||||
email_company: 'ایمیل کمپانی برای اشخاص حقوقی الزامی است',
|
||||
company_name: 'درصورتی که شخص حقوقی هستید، نام کمپانی را وارد کنید',
|
||||
username: 'نام کاربری را وارد کنید',
|
||||
phone_number: 'شماره تماس را وارد کنید',
|
||||
password: 'پسورد را وارد کنید',
|
||||
password_confirmation: 'پسورد ها یکی نیست',
|
||||
// addressing validations
|
||||
country: 'کشور را وارد کنید',
|
||||
province: 'استان را وارد کنید',
|
||||
city: 'شهر را وارد کنید',
|
||||
address: 'آدرس را وارد کنید',
|
||||
postal_code: 'کد پستی را وارد کنید',
|
||||
plaque: 'پلاک را وارد کنید',
|
||||
receiver_first_name: 'نام گیرنده را وارد کنید',
|
||||
receiver_last_name: 'نام خانوادگی گیرنده را وارد کنید',
|
||||
receiver_mobile: 'شماره موبایل گیرنده را وارد کنید',
|
||||
// global (post - gallery - ...)
|
||||
title: 'عنوان را وارد کنید',
|
||||
caption: 'متن را وارد کنید',
|
||||
description: 'توضیحات را وارد کنید',
|
||||
category: 'دسته بندی را انتخاب کنید',
|
||||
image: 'عکس اجباری است',
|
||||
cover: 'کاور اجباری است',
|
||||
message: 'پیام را بنویسید',
|
||||
quantity: 'تعداد را وارد کنید'
|
||||
},
|
||||
format: {
|
||||
phone_number: 'فرمت شماره تماس صحیح نیست',
|
||||
email: 'فرمت ایمیل قابل قبول نیست',
|
||||
number: 'مقدار باید از جنس عدد باشد',
|
||||
boolean: 'مقدار باید از جنس Boolean باشد',
|
||||
},
|
||||
min_char: {
|
||||
min2: 'حداقل 2 کاراکتر',
|
||||
min4: 'حداقل 4 کاراکتر',
|
||||
min8: 'حداقل 8 کاراکتر',
|
||||
min10: 'حداقل 10 کاراکتر',
|
||||
min20: 'حداقل 20 کاراکتر',
|
||||
min30: 'حداقل 30 کاراکتر',
|
||||
min40: 'حداقل 40 کاراکتر',
|
||||
min50: 'حداقل 50 کاراکتر',
|
||||
min60: 'حداقل 60 کاراکتر',
|
||||
min100: 'حداقل 100 کاراکتر',
|
||||
min120: 'حداقل 120 کاراکتر',
|
||||
min150: 'حداقل 150 کاراکتر',
|
||||
min200: 'حداقل 200 کاراکتر',
|
||||
data_size: 'حجم قابل قبول حداقل: ',
|
||||
image_width_size: 'عرض حداقل: ',
|
||||
image_height_size: 'ارتفاع حداقل: ',
|
||||
},
|
||||
max_char: {
|
||||
max4: 'حداکثر 4 کاراکتر',
|
||||
max8: 'حداکثر 8 کاراکتر',
|
||||
max10: 'حداکثر 10 کاراکتر',
|
||||
max15: 'حداکثر 15 کاراکتر',
|
||||
max20: 'حداکثر 20 کاراکتر',
|
||||
max30: 'حداکثر 30 کاراکتر',
|
||||
max40: 'حداکثر 40 کاراکتر',
|
||||
max50: 'حداکثر 50 کاراکتر',
|
||||
max60: 'حداکثر 60 کاراکتر',
|
||||
max100: 'حداکثر 100 کاراکتر',
|
||||
max120: 'حداکثر 120 کاراکتر',
|
||||
max150: 'حداکثر 150 کاراکتر',
|
||||
max200: 'حداکثر 200 کاراکتر',
|
||||
data_size: 'حجم قابل قبول حداکثر: ',
|
||||
image_width_size: 'عرض حداکثر: ',
|
||||
image_height_size: 'ارتفاع حداکثر: ',
|
||||
},
|
||||
not_found: {
|
||||
user_id: 'کاربری با این مشخصات وجود ندارد',
|
||||
admin_id: 'ادمینی با این مشخصات وجود ندارد',
|
||||
order_id: 'سفارشی با این مشخصات وجود ندارد',
|
||||
item_id: 'موردی با این مشخصات وجود ندارد',
|
||||
password: 'رمز عبور اشتباه است'
|
||||
},
|
||||
duplicated: {
|
||||
username: 'این نام کاربری از قبل وجود دارد',
|
||||
email: 'این ایمیل از قبل وجود دارد',
|
||||
name: 'نام تکراری است',
|
||||
title: 'عنوان تکراری است'
|
||||
},
|
||||
response: {
|
||||
logged_in: 'شما وارد سیستم شدید',
|
||||
not_logged_in: 'شما وارد سیستم نشدید',
|
||||
logged_out: 'شما از سیستم خارج شدید',
|
||||
unauthenticated: 'غیرمجاز',
|
||||
recovery_link: 'لینک بازیابی فرستاده شد',
|
||||
success_save: 'با موفقیت ثبت شد',
|
||||
success_remove: 'با موفقیت حذف شد',
|
||||
cart_empty: 'سبد خرید خالی است',
|
||||
already_has_address: 'آدرس قبلا اضافه شده',
|
||||
expired_reset_link: 'این لینک بازیابی منقضی شده است',
|
||||
email_not_confirmed: 'ابتدا ایمیل خود را تایید کنید،لینک فعال سازی قبلا برای شما فرستاده شده است.',
|
||||
expired_activation_link: 'این لینک فعال سازی منقضی شده است',
|
||||
success_activation: 'اکانت شما با موفقیت فعال شد'
|
||||
}
|
||||
},
|
||||
en: {
|
||||
required: {
|
||||
// developer validations
|
||||
remember_me: 'Remember_me parameter required',
|
||||
// registration validations
|
||||
first_name: 'Enter name',
|
||||
last_name: 'Enter last name',
|
||||
email: 'Enter email',
|
||||
email_personal: 'Personal email is required',
|
||||
email_company: 'Company email is required for legal entities',
|
||||
company_name: 'Enter company name if you are a legal entity',
|
||||
username: 'Enter username',
|
||||
phone_number: 'Enter phone number',
|
||||
password: 'Enter password',
|
||||
password_confirmation: 'Passwords are not the same',
|
||||
// addressing validations
|
||||
country: 'Enter country',
|
||||
province: 'Enter province',
|
||||
city: 'Enter city',
|
||||
address: 'Enter address',
|
||||
postal_code: 'Enter postal code',
|
||||
plaque: 'Enter plaque',
|
||||
receiver_first_name: 'Enter recipient name',
|
||||
receiver_last_name: 'Enter recipient surname',
|
||||
receiver_mobile: 'Enter recipient\'s mobile number',
|
||||
// global (post - gallery - ...)
|
||||
title: 'Enter title',
|
||||
caption: 'Enter caption',
|
||||
description: 'Enter description',
|
||||
category: 'Select category',
|
||||
image: 'Image is required',
|
||||
cover: 'Cover is required',
|
||||
message: 'Write message',
|
||||
quantity: 'Enter quantity'
|
||||
},
|
||||
format: {
|
||||
phone_number: 'Phone number format in incorrect',
|
||||
email: 'Email format not correct',
|
||||
number: 'Value must be number',
|
||||
boolean: 'Value must be Boolean',
|
||||
},
|
||||
min_char: {
|
||||
min2: 'At least 2 characters',
|
||||
min4: 'At least 4 characters',
|
||||
min8: 'At least 8 characters',
|
||||
min10: 'At least 10 characters',
|
||||
min20: 'At least 20 characters',
|
||||
min30: 'At least 30 characters',
|
||||
min40: 'At least 40 characters',
|
||||
min50: 'At least 50 characters',
|
||||
min60: 'At least 60 characters',
|
||||
min100: 'At least 100 characters',
|
||||
min120: 'At least 120 characters',
|
||||
min150: 'At least 150 characters',
|
||||
min200: 'At least 200 characters',
|
||||
data_size: 'Acceptable minimum size: ',
|
||||
image_width_size: 'Minimum width: ',
|
||||
image_height_size: 'Minimum height: ',
|
||||
},
|
||||
max_char: {
|
||||
max4: 'Maximum 4 characters',
|
||||
max8: 'Maximum 8 characters',
|
||||
max10: 'Maximum 10 characters',
|
||||
max15: 'Maximum 15 characters',
|
||||
max20: 'Maximum 20 characters',
|
||||
max30: 'Maximum 30 characters',
|
||||
max40: 'Maximum 40 characters',
|
||||
max50: 'Maximum 50 characters',
|
||||
max60: 'Maximum 60 characters',
|
||||
max100: 'Maximum 100 characters',
|
||||
max120: 'Maximum 120 characters',
|
||||
max150: 'Maximum 150 characters',
|
||||
max200: 'Maximum 200 characters',
|
||||
data_size: 'Maximum acceptable size: ',
|
||||
image_width_size: 'Maximum width: ',
|
||||
image_height_size: 'Maximum height: ',
|
||||
},
|
||||
not_found: {
|
||||
user_id: 'There is no user with this profile',
|
||||
admin_id: 'There is no admin with this profile',
|
||||
order_id: 'There is no order with this profile',
|
||||
item_id: 'There is no item with this specification',
|
||||
password: 'Password is incorrect'
|
||||
},
|
||||
duplicated: {
|
||||
username: 'This username already exists',
|
||||
email: 'This email already exists',
|
||||
name: 'Name is duplicate',
|
||||
title: 'Title is duplicate'
|
||||
},
|
||||
response: {
|
||||
logged_in: 'You are logged in',
|
||||
not_logged_in: 'You are not logged in',
|
||||
logged_out: 'You are logged out',
|
||||
unauthenticated: 'unauthenticated',
|
||||
recovery_link: 'Recovery link sent',
|
||||
success_save: 'Successfully saved',
|
||||
success_remove: 'Successfully removed',
|
||||
cart_empty: 'Cart is empty',
|
||||
already_has_address: 'Already has address',
|
||||
expired_reset_link: 'The current reset pass link has been expired',
|
||||
email_not_confirmed: 'Confirm your email first, the activation link has already been sent to you.',
|
||||
expired_activation_link: 'This activation link has expired',
|
||||
success_activation: 'Your account has been successfully activated'
|
||||
}
|
||||
},
|
||||
de: {
|
||||
required: {
|
||||
// developer validations
|
||||
remember_me: 'Remember_me-Parameter erforderlich',
|
||||
// registration validations
|
||||
first_name: 'Name eingeben',
|
||||
last_name: 'Nachnamen eingeben',
|
||||
email: 'Email eingeben',
|
||||
email_personal: 'Persönliche E-Mail ist erforderlich',
|
||||
email_company: 'Für juristische Personen ist eine Unternehmens-E-Mail erforderlich',
|
||||
company_name: 'Geben Sie den Firmennamen ein, wenn Sie eine juristische Person sind',
|
||||
username: 'Geben Sie den Benutzernamen ein',
|
||||
phone_number: 'Telefonnummer eingeben',
|
||||
password: 'Passwort eingeben',
|
||||
password_confirmation: 'Passwörter sind nicht dasselbe',
|
||||
// addressing validations
|
||||
country: 'Land eingeben',
|
||||
province: 'Stadt betreten',
|
||||
city: 'Stadt betreten',
|
||||
address: 'Adresse eingeben',
|
||||
postal_code: 'Postleitzahl eingeben',
|
||||
plaque: 'Plakette eingeben',
|
||||
receiver_first_name: 'Empfängername eingeben',
|
||||
receiver_last_name: 'Nachname des Empfängers eingeben',
|
||||
receiver_mobile: 'Handynummer des Empfängers eingebenr',
|
||||
// global (post - gallery - ...)
|
||||
title: 'Titel eingeben',
|
||||
caption: 'Beschriftung eingeben',
|
||||
description: 'Beschreibung eingeben',
|
||||
category: 'Kategorie wählen',
|
||||
image: 'Bild ist erforderlich',
|
||||
cover: 'Bild ist erforderlich Abdeckung ist erforderlich',
|
||||
message: 'Nachricht schreiben',
|
||||
quantity: 'Menge eingeben'
|
||||
},
|
||||
format: {
|
||||
phone_number: 'Telefonnummernformat falsch',
|
||||
email: 'E-Mail-Format nicht korrekt',
|
||||
number: 'Wert muss Nummer sein',
|
||||
boolean: 'Wert muss Boolescher Wert sein',
|
||||
},
|
||||
min_char: {
|
||||
min2: 'Mindestens 2 Zeichen',
|
||||
min4: 'Mindestens 4 Zeichen',
|
||||
min8: 'Mindestens 8 Zeichen',
|
||||
min10: 'Mindestens 10 Zeichen',
|
||||
min20: 'Mindestens 20 Zeichen',
|
||||
min30: 'Mindestens 30 Zeichen',
|
||||
min40: 'Mindestens 40 Zeichen',
|
||||
min50: 'Mindestens 50 Zeichen',
|
||||
min60: 'Mindestens 60 Zeichen',
|
||||
min100: 'Mindestens 100 Zeichen',
|
||||
min120: 'Mindestens 120 Zeichen',
|
||||
min150: 'Mindestens 150 Zeichen',
|
||||
min200: 'Mindestens 200 Zeichen',
|
||||
data_size: 'Akzeptable Mindestgröße: ',
|
||||
image_width_size: 'Mindestbreite: ',
|
||||
image_height_size: 'Mindesthöhe: ',
|
||||
},
|
||||
max_char: {
|
||||
max4: 'Maximal 4 Zeichen',
|
||||
max8: 'Maximal 8 Zeichen',
|
||||
max10: 'Maximal 10 Zeichen',
|
||||
max15: 'Maximal 15 Zeichen',
|
||||
max20: 'Maximal 20 Zeichen',
|
||||
max30: 'Maximal 30 Zeichen',
|
||||
max40: 'Maximal 40 Zeichen',
|
||||
max50: 'Maximal 50 Zeichen',
|
||||
max60: 'Maximal 60 Zeichen',
|
||||
max100: 'Maximal 100 Zeichen',
|
||||
max120: 'Maximal 120 Zeichen',
|
||||
max150: 'Maximal 150 Zeichen',
|
||||
max200: 'Maximal 200 Zeichen',
|
||||
data_size: 'Maximal zulässige Größe: ',
|
||||
image_width_size: 'Maximale Breite: ',
|
||||
image_height_size: 'Maximale Höhe: ',
|
||||
},
|
||||
not_found: {
|
||||
user_id: 'Es gibt keinen Benutzer mit diesem Profil',
|
||||
admin_id: 'Es gibt keinen Administrator mit diesem Profil',
|
||||
order_id: 'Es gibt keine Bestellung mit diesem Profil',
|
||||
item_id: 'Es gibt keinen Artikel mit dieser Spezifikation',
|
||||
password: 'Passwort ist falsch'
|
||||
},
|
||||
duplicated: {
|
||||
username: 'Dieser Benutzername existiert bereits',
|
||||
email: 'Diese E-Mail existiert bereits',
|
||||
name: 'Name ist doppelt',
|
||||
title: 'Titel ist doppelt'
|
||||
},
|
||||
response: {
|
||||
logged_in: 'Sie sind angemeldet',
|
||||
not_logged_in: 'Sie sind nicht angemeldet',
|
||||
logged_out: 'Sie sind abgemeldet',
|
||||
unauthenticated: 'nicht authentifiziert',
|
||||
recovery_link: 'Wiederherstellungslink gesendet',
|
||||
success_save: 'Erfolgreich gespeichert',
|
||||
success_remove: 'Erfolgreich entfernt',
|
||||
cart_empty: 'Warenkorb ist leer',
|
||||
ready_has_address: 'Hat bereits Adresse',
|
||||
expired_reset_link: 'Der aktuelle Reset-Pass-Link ist abgelaufen',
|
||||
email_not_confirmed: "Bestätigen Sie zuerst Ihre E-Mail, der Aktivierungslink wurde bereits an Sie gesendet.",
|
||||
expired_activation_link: 'Dieser Aktivierungslink ist abgelaufen',
|
||||
success_activation: 'Ihr Konto wurde erfolgreich aktiviert'
|
||||
}
|
||||
},
|
||||
tr: {
|
||||
required: {
|
||||
// geliştirici doğrulamaları
|
||||
Remember_me: 'Remember_me parametresi gerekli',
|
||||
// kayıt doğrulamaları
|
||||
first_name: 'Adı girin',
|
||||
last_name: 'Soyadı girin',
|
||||
email: 'E-posta girin',
|
||||
email_personal: 'Kişisel e-posta gereklidir',
|
||||
email_company: 'Tüzel kişiler için şirket e-postası gereklidir',
|
||||
company_name: 'Tüzel kişiyseniz şirket adını girin',
|
||||
username: 'Kullanıcı adını girin',
|
||||
phone_number: 'Telefon numarasını girin',
|
||||
password: 'Şifre girin',
|
||||
password_confirmation: 'Şifreler aynı değil',
|
||||
// doğrulamaları adresleme
|
||||
country: 'Ülke girin',
|
||||
province: 'İl girin',
|
||||
city: 'Şehir girin',
|
||||
address: 'Adres girin',
|
||||
postal_code: 'Posta kodunu girin',
|
||||
plaque: 'Plak girin',
|
||||
receiver_first_name: 'Alıcı adını girin',
|
||||
receiver_last_name: 'Alıcının soyadını girin',
|
||||
receiver_mobile: 'Alıcının cep telefonu numarasını girin',
|
||||
// global (post - galeri - ...)
|
||||
title: 'Başlığı girin',
|
||||
caption: 'Başlık girin',
|
||||
description: 'Açıklama girin',
|
||||
category: 'Kategori seçin',
|
||||
image: 'Resim gerekli',
|
||||
cover: 'Kapak gereklidir',
|
||||
message: 'Mesaj yaz',
|
||||
quantity: 'Miktar girin'
|
||||
},
|
||||
format: {
|
||||
phone_number: 'Telefon numarası biçimi yanlış',
|
||||
email: 'E-posta formatı doğru değil',
|
||||
number: 'Değer sayı olmalıdır',
|
||||
boolean: 'Değer Boole olmalıdır',
|
||||
},
|
||||
min_char: {
|
||||
min2: 'En az 2 karakter',
|
||||
min4: 'En az 4 karakter',
|
||||
min8: 'En az 8 karakter',
|
||||
min10: 'En az 10 karakter',
|
||||
min20: 'En az 20 karakter',
|
||||
min30: 'En az 30 karakter',
|
||||
min40: 'En az 40 karakter',
|
||||
min50: 'En az 50 karakter',
|
||||
min60: 'En az 60 karakter',
|
||||
min100: 'En az 100 karakter',
|
||||
min120: 'En az 120 karakter',
|
||||
min150: 'En az 150 karakter',
|
||||
min200: 'En az 200 karakter',
|
||||
data_size: 'Kabul edilebilir minimum boyut: ',
|
||||
image_width_size: 'Minimum genişlik: ',
|
||||
image_height_size: 'Minimum yükseklik: ',
|
||||
},
|
||||
max_char: {
|
||||
max4: 'Maksimum 4 karakter',
|
||||
max8: 'Maksimum 8 karakter',
|
||||
max10: 'Maksimum 10 karakter',
|
||||
max15: 'Maksimum 15 karakter',
|
||||
max20: 'Maksimum 20 karakter',
|
||||
max30: 'Maksimum 30 karakter',
|
||||
max40: 'Maksimum 40 karakter',
|
||||
max50: 'Maksimum 50 karakter',
|
||||
max60: 'Maksimum 60 karakter',
|
||||
max100: 'Maksimum 100 karakter',
|
||||
max120: 'Maksimum 120 karakter',
|
||||
max150: 'Maksimum 150 karakter',
|
||||
max200: 'Maksimum 200 karakter',
|
||||
data_size: 'Kabul edilebilir maksimum boyut: ',
|
||||
image_width_size: 'Maksimum genişlik: ',
|
||||
image_height_size: 'Maksimum yükseklik: ',
|
||||
},
|
||||
not_found: {
|
||||
user_id: 'Bu profile sahip kullanıcı yok',
|
||||
admin_id: 'Bu profile sahip yönetici yok',
|
||||
order_id: 'Bu profilde sipariş yok',
|
||||
item_id: 'Bu spesifikasyona sahip hiçbir öğe yok',
|
||||
password: 'Şifre yanlış'
|
||||
},
|
||||
duplicated: {
|
||||
username: 'Bu kullanıcı adı zaten mevcut',
|
||||
email: 'Bu email zaten var',
|
||||
name: 'Ad çift',
|
||||
title: 'Başlık yineleniyor'
|
||||
},
|
||||
response: {
|
||||
logged_in: 'Giriş yaptınız',
|
||||
not_logged_in: 'Giriş yapmadınız',
|
||||
logged_out: 'Çıkış yaptınız',
|
||||
unauthenticated: 'unauthenticated',
|
||||
recovery_link: 'Kurtarma bağlantısı gönderildi',
|
||||
success_save: 'Başarıyla kaydedildi',
|
||||
success_remove: 'Başarıyla kaldırıldı',
|
||||
cart_empty: 'Sepet boş',
|
||||
already_has_address: 'Zaten adresi var',
|
||||
expired_reset_link: 'Mevcut sıfırlama geçiş bağlantısının süresi doldu',
|
||||
email_not_confirmed: 'Önce e-postanızı onaylayın, aktivasyon bağlantısı size zaten gönderildi.',
|
||||
expired_activation_link: "Bu aktivasyon bağlantısının süresi doldu",
|
||||
success_activation: 'Hesabınız başarıyla etkinleştirildi'
|
||||
}
|
||||
},
|
||||
it: {
|
||||
required: {
|
||||
// convalide dello sviluppatore
|
||||
Remember_me: "Remember_me parameter required",
|
||||
// convalide della registrazione
|
||||
first_name: "Inserisci nome",
|
||||
last_name: "Inserisci il cognome",
|
||||
email: "Enter email",
|
||||
email_personal: "L'email personale è obbligatoria",
|
||||
email_company: "L'email aziendale è obbligatoria per le persone giuridiche",
|
||||
company_name: "Inserisci il nome dell'azienda se sei una persona giuridica",
|
||||
username: "Inserisci nome utente",
|
||||
phone_number: "Inserisci numero di telefono",
|
||||
password: "Inserisci password",
|
||||
password_confirmation: "Le password non sono le stesse",
|
||||
// indirizzamento delle convalide
|
||||
country: "Inserisci paese",
|
||||
province: "Inserisci provincia",
|
||||
city: "Inserisci città",
|
||||
address: "Inserisci indirizzo",
|
||||
postal_code: "Inserisci codice postale",
|
||||
plaque: "Inserisci targa",
|
||||
receiver_first_name: "Inserisci il nome del destinatario",
|
||||
receiver_last_name: "Inserisci il cognome del destinatario",
|
||||
receiver_mobile: "Inserisci il numero di cellulare del destinatario",
|
||||
// globale (post - gallery - ...)
|
||||
title: "Inserisci titolo",
|
||||
caption: "Inserisci didascalia",
|
||||
description: "Inserisci descrizione",
|
||||
category: "Seleziona categoria",
|
||||
image: "L'immagine è obbligatoria",
|
||||
cover: "Cover is required",
|
||||
message: "Scrivi messaggio",
|
||||
quantity: "Inserisci quantità"
|
||||
},
|
||||
format: {
|
||||
phone_number: "Formato del numero di telefono non corretto",
|
||||
email: "Formato email non corretto",
|
||||
number: "Il valore deve essere un numero",
|
||||
boolean: "Il valore deve essere booleano",
|
||||
},
|
||||
min_char: {
|
||||
min2: "Almeno 2 caratteri",
|
||||
min4: "Almeno 4 caratteri",
|
||||
min8: "Almeno 8 caratteri",
|
||||
min10: "Almeno 10 caratteri",
|
||||
min20: "Almeno 20 caratteri",
|
||||
min30: "Almeno 30 caratteri",
|
||||
min40: "Almeno 40 caratteri",
|
||||
min50: "Almeno 50 caratteri",
|
||||
min60: "Almeno 60 caratteri",
|
||||
min100: "Almeno 100 caratteri",
|
||||
min120: "Almeno 120 caratteri",
|
||||
min150: "Almeno 150 caratteri",
|
||||
min200: "Almeno 200 caratteri",
|
||||
data_size: "Dimensione minima accettabile: ",
|
||||
image_width_size: "Larghezza minima: ",
|
||||
image_height_size: "Altezza minima: ",
|
||||
},
|
||||
max_char: {
|
||||
max4: "Massimo 4 caratteri",
|
||||
max8: "Massimo 8 caratteri",
|
||||
max10: "Massimo 10 caratteri",
|
||||
max15: "Massimo 15 caratteri",
|
||||
max20: "Massimo 20 caratteri",
|
||||
max30: "Massimo 30 caratteri",
|
||||
max40: "Massimo 40 caratteri",
|
||||
max50: "Massimo 50 caratteri",
|
||||
max60: "Massimo 60 caratteri",
|
||||
max100: "Massimo 100 caratteri",
|
||||
max120: "Massimo 120 caratteri",
|
||||
max150: "Massimo 150 caratteri",
|
||||
max200: "Massimo 200 caratteri",
|
||||
data_size: "Dimensione massima accettabile: ",
|
||||
image_width_size: "Larghezza massima: ",
|
||||
image_height_size: "Altezza massima: ",
|
||||
},
|
||||
not_found: {
|
||||
user_id: "Nessun utente con questo profilo",
|
||||
admin_id: "Nessun amministratore con questo profilo",
|
||||
order_id: "Nessun ordine con questo profilo",
|
||||
item_id: "Nessun articolo con questa specifica",
|
||||
password: "La password non è corretta"
|
||||
},
|
||||
duplicated: {
|
||||
username: "Questo nome utente esiste già",
|
||||
email: "Questa email esiste già",
|
||||
name: "Il nome è duplicato",
|
||||
title: "Il titolo è duplicato"
|
||||
},
|
||||
response: {
|
||||
logged_in: "Hai effettuato l'accesso",
|
||||
not_logged_in: "Non sei loggato",
|
||||
logged_out: "Sei disconnesso",
|
||||
unauthenticated: "unauthenticated",
|
||||
recovery_link: "Link di ripristino inviato",
|
||||
success_save: "Salvataggio riuscito",
|
||||
success_remove: "Rimosso con successo",
|
||||
cart_empty: "Il carrello è vuoto",
|
||||
already_has_address: "Ha già indirizzo",
|
||||
expired_reset_link: "L'attuale link del passaggio di reimpostazione è scaduto",
|
||||
email_not_confirmed: "Conferma prima la tua email, il link di attivazione ti è già stato inviato.",
|
||||
expired_activation_link: "Questo link di attivazione è scaduto",
|
||||
success_activation: "Il tuo account è stato attivato con successo"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user