diff --git a/backend/_old/backend.zip b/backend/_old/backend.zip new file mode 100644 index 0000000..48f165a Binary files /dev/null and b/backend/_old/backend.zip differ diff --git a/backend/api (2).xls b/backend/api (2).xls new file mode 100644 index 0000000..34927f9 Binary files /dev/null and b/backend/api (2).xls differ diff --git a/backend/app.js b/backend/app.js index 8f5d343..f2a6b18 100644 --- a/backend/app.js +++ b/backend/app.js @@ -15,7 +15,7 @@ BigInt.prototype.toJSON = function () { return Number(this) } -app.use((req, res, next) => { +/* app.use((req, res, next) => { if(!(req.body instanceof Object)) return next() @@ -26,29 +26,17 @@ app.use((req, res, next) => { .map(key => req.body[key] = escapeHtml(req.body[key])) next() -}) +}) */ -// cors -app.use((req, res, next) => { - res.set({ - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE', - 'Access-Control-Allow-Headers': 'Accept,Accept-Language,Content-Language,Content-Type,Authorization,Cookie,X-Requested-With,Origin,Host', - 'Access-Control-Allow-Credentials': true - }) - - return req.method == 'OPTIONS' ? res.status(200).json({success: true}) : next() -}) - -app.post('(/api/admin/customer/login|/api/miniapp/user/login)', (req, res, next) => { +app.post('(/api/admin/auth/telegram|/api/miniapp/auth)', (req, res, next) => { const data = Object.assign({}, req.query) delete data.hash const hash = req.query?.hash const BOT_TOKEN = '7236504417:AAGVaodw3cRwGlf-jAhwnYb51OHaXcgpW8k' - const dataCheckString = Object.keys(data).sort().map((key) => `${key}=${data[key]}`).join("\n") - const secretKey = crypto.createHmac("sha256", "WebAppData").update(BOT_TOKEN).digest() - const hmac = crypto.createHmac("sha256", secretKey).update(dataCheckString).digest("hex") + const dataCheckString = Object.keys(data).sort().map((key) => `${key}=${data[key]}`).join('\n') + const secretKey = crypto.createHmac('sha256', 'WebAppData').update(BOT_TOKEN).digest() + const hmac = crypto.createHmac('sha256', secretKey).update(dataCheckString).digest('hex') const timeDiff = Date.now() / 1000 - data.auth_date @@ -73,14 +61,9 @@ app.use((err, req, res, next) => { console.error(`Error for ${req.path}: ${err}`) let message, code - //if (err.code == 'SQLITE_ERROR' || err.code == 'SQLITE_CONSTRAINT_CHECK') { - // message = 'DATABASE_ERROR' - //code = err.code == 'SQLITE_CONSTRAINT_CHECK' ? 400 : 500 - //} else { - [message, code = 500] = err.message.split('::') - //} + [message, code = 500] = err.message.split('::') - res.status(res.statusCode == 200 ? 500 : res.statusCode).json({success: false, error: { message, code}}) + res.status(code).json({success: false, error: { message, code}}) }) app.use(express.static('public')) diff --git a/backend/apps/admin.js b/backend/apps/admin.js index 854a091..baafc63 100644 --- a/backend/apps/admin.js +++ b/backend/apps/admin.js @@ -15,11 +15,10 @@ const upload = multer({ }) const sessions = {} +const emailCache = {} // key = email, value = code app.use((req, res, next) => { - if (req.path == '/customer/login' || - req.path == '/customer/register' || - req.path == '/customer/activate') + if (req.path == '/auth/email' || req.path == '/auth/telegram' || req.path == '/auth/register' || req.path == '/auth/logout') return next() const asid = req.query.asid || req.cookies.asid @@ -31,96 +30,104 @@ app.use((req, res, next) => { next() }) -// CUSTOMER -app.post('/customer/login', (req, res, next) => { +// AUTH +function createSession(req, res, customer_id) { + if (!customer_id) + throw Error('AUTH_ERROR::500') + + res.locals.customer_id = customer_id + const asid = crypto.randomBytes(64).toString('hex') + req.session = sessions[asid] = {asid, customer_id } + res.setHeader('Set-Cookie', [`asid=${asid};httpOnly;path=/api/admin`]) +} + +app.post('/auth/email', (req, res, next) => { res.locals.email = req.body?.email res.locals.password = req.body?.password - let customer_id = db - .prepare(` - select id - from customers - where is_active = 1 and ( - email is not null and email = :email and password is not null and password = :password or - email is null and password is null and telegram_user_id = :telegram_id - ) - `) + const customer_id = db + .prepare(`select id from customers where is_blocked = 0 and email = :email and password is not null and password = :password `) .pluck(true) .get(res.locals) - if (!customer_id && !res.locals.email && !res.locals.password) { - customer_id = db - .prepare(`insert into customers (telegram_user_id, is_active) values (:telegram_id, 1) returning id`) - .safeIntegers(true) - .pluck(true) - .get(res.locals) - } - if (!customer_id) throw Error('AUTH_ERROR::401') - res.locals.customer_id = customer_id - db - .prepare(`update customers set telegram_user_id = :telegram_id where id = :customer_id and email is not null`) - .run(res.locals) - - const asid = crypto.randomBytes(64).toString('hex') - req.session = sessions[asid] = {asid, customer_id } - res.setHeader('Set-Cookie', [`asid=${asid};httpOnly;path=/api/admin`]) - + createSession(req, res, customer_id) res.status(200).json({success: true}) }) -app.get('/customer/logout', (req, res, next) => { - delete sessions[req.session.asid] - res.setHeader('Set-Cookie', [`asid=; expired; httpOnly`]) +app.post('/auth/telegram', (req, res, next) => { + let customer_id = db + .prepare(`select id from customers where is_blocked = 0 and telegram_id = :telegram_id`) + .pluck(true) + .get(res.locals) || db + .prepare(`replace into customers (telegram_id, is_blocked) values (:telegram_id, 0) returning id`) + .pluck(true) + .get(res.locals) + + createSession(req, res, customer_id) res.status(200).json({success: true}) }) -app.post('/customer/register', (req, res, next) => { - const email = String(req.body.email).trim() - const password = String(req.body.password).trim() +app.get('/auth/logout', (req, res, next) => { + if (req.session?.asid) + delete sessions[req.session.asid] + res.setHeader('Set-Cookie', [`asid=; expired; httpOnly;path=/api/admin`]) + res.status(200).json({success: true}) +}) - const validateEmail = email => String(email).toLowerCase().match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/) - if (!validateEmail(email)) +app.post('/auth/register', (req, res, next) => { + const email = String(req.body.email ?? '').trim() + const code = String(req.body.code ?? '').trim() + const password = String(req.body.password ?? '').trim() + + if (email) { + const validateEmail = email => String(email).toLowerCase().match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/) + if (!validateEmail(email)) throw Error('INCORRECT_EMAIL::400') - - if (!password) - throw Error('EMPTY_PASSWORD::400') - - const row = db + + const customer_id = db .prepare('select id from customers where email = :email') - .run({email}) - if (row) - throw Error('DUPLICATE_EMAIL::400') + .pluck(true) + .get({email}) + + if (customer_id) + throw Error('USED_EMAIL::400') + } + + if (email && !code) { + const code = Math.random().toString().substr(2, 4) + emailCache[email] = code + // To-Do: send email + console.log(`${email} => ${code}`) + } + + if (email && code && !password) { + if (emailCache[email] != code) + throw Error('INCORRECT_CODE::400') + } + + if (email && code && password) { + if (password.length < 8) + throw Error('INCORRECT_PASSWORD::400') + + db + .prepare('insert into customers (email, password, is_blocked) values (:email, :password, 0)') + .run({email, password}) + } + + res.status(200).json({success: true}) + }) - const key = crypto.randomBytes(32).toString('hex') - const info = db - .prepare('insert into customers (email, password, activation_key) values (:email, :password, :key)') - .run({email, password, key}) - - // To-Do: SEND MAIL - console.log(`http://127.0.0.1:3000/api/customer/activate?key=${key}`) - res.status(200).json({success: true, data: key}) -}) - -app.get('/customer/activate', (req, res, next) => { - const row = db - .prepare('update customers set is_active = 1 where activation_key = :key returning id') - .get({key: req.query.key}) - - if (!row || !row.id) - throw Error('BAD_ACTIVATION_KEY::400') - - res.status(200).json({success: true}) -}) +// CUSTOMER app.get('/customer/profile', (req, res, next) => { const row = db .prepare(` select id, name, email, plan, coalesce(json_balance, '{}') json_balance, coalesce(json_company, '{}') json_company, upload_group_id from customers - where id = :customer_id and is_active = 1 + where id = :customer_id `) .get(res.locals) diff --git a/backend/apps/bot.js b/backend/apps/bot.js index 963680c..17c9c71 100644 --- a/backend/apps/bot.js +++ b/backend/apps/bot.js @@ -10,8 +10,9 @@ const { NewMessage } = require('telegram/events') const { Button } = require('telegram/tl/custom/button') const { CustomFile } = require('telegram/client/uploads') -// const session = new StringSession('1AgAOMTQ5LjE1NC4xNjcuNTABuxdIxmjimA0hmWpdrlZ4Fo7uoIGU4Bu9+G5QprS6zdtyeMfcssWEZp0doLRX/20MomQyF4Opsos0El0Ifj5aiNgg01z8khMLMeT98jS+1U/sh32p3GxZfxyXSxX1bD0NLRaXnqVyNNswYqRZPhboT28NMjDqwlz0nrW9rge+QMJDL7jIkXgSs+cmJBINiqsEI8jWjXmc8TU/17gngtjUHRf5kRM4y5gsNC4O8cF5lcHRx0G/U5ZVihTID8ItQ6EdEHjz6e4XErbVOJ81PfYkqEoPXVvkEmRM0/VbvCzFfixfas4Vzczfn98OHLd8P2MXcgokZ2rppvIV3fQXOHxJbA0=') -const session = new StringSession('') +//const session = new StringSession('1AgAOMTQ5LjE1NC4xNjcuNTABu2OaFuD5Oyi5wGck+n5ldAfshzYfwlWee+OUxYBvFzlKAdW11Hsndu1SJBLUnKjP8sTJEPbLwdqANBhBXmQMghLVAblwK6TxLfsWxy2zf/HGLeNXohhrsep0hBxu9imyHV6OI6gQG+c5qaGkzjZrz0AcS4ut0xy99XrXgjiNfnjeMX7a0mOk6IK9iKdwbX9kXTfclFLVppiBGXolYJjVb2E57tk4+7RncIVyw+Fxn0NZfnhEfHJZly6j03arZOeM5VYl9ul8+3lJDD+KJJHeMgImmYjmcFcF3CbtkhPuTSPnWKtCnm2sRzepn5VFfoG6zgYff04fBdKGvHAai+wQSOY=') +const session = new StringSession('1AgAOMTQ5LjE1NC4xNjcuNTEBuzSgmBQR5/m8M8cyOnsLCIOkYQJTizJoJRZiPKK+eBjMuodc0JuKQwzeWBRJI/c6YxaBHvokpngf5kr57uly+meSPPlFq6MyoSSQDbEJ3VAAWJu+/ALN0ickE92RjRfM5Kw6DimC9FXuMgJJsoUHtk/i+ZGXy9JB+q67G0yy8NvFIuWpFHJDkwmi0qTlTgJ5UOm4PYkV01iNUcV5siaWFVTTLsetHtBUdMOzg5WjjvuOyYV/MIx+z7ynhvF3DxLPCugxqhCvZ/RW+0vldrTX5TZ0BzIDk2eNFQjRORJcZo6upwvH7aZYStV4DxhIi1dEYu5gyvnt4vkbR5kuvE/GqO0=') + let client @@ -493,12 +494,19 @@ async function onNewUserMessage (msg) { updateUser(userId, user) await updateUserPhoto (userId, user) + const appButton = new Api.KeyboardButtonWebView({ + text: "Open Mini-App", // Текст на кнопке + url: "https://h5sj0gpz-3000.euw.devtunnels.ms/", // URL вашего Mini-App (HTTPS!) + }); + + const inputPeer = new Api.InputPeerUser({userId: tgUserId, accessHash: user.accessHash.value}) const resultBtn = await client.sendMessage(inputPeer, { message: 'Сообщение от бота', buttons: client.buildReplyMarkup([ [Button.url('Админка', 'https://t.me/ready_or_not_2025_bot/userapp?startapp=admin')], - [Button.url('Пользователь', 'https://t.me/ready_or_not_2025_bot/userapp?startapp=user')] + [Button.url('Пользователь', 'https://t.me/ready_or_not_2025_bot/userapp?startapp=user')], + [appButton] ]) }) } catch (err) { @@ -560,6 +568,7 @@ class Bot extends EventEmitter { }) await client.start({botAuthToken}) + console.log('SID: ', session.save()) } async uploadDocument(projectId, fileName, mime, data, parentType, parentId, publishedBy) { diff --git a/backend/data/db.sqlite b/backend/data/db.sqlite index 438da8f..9ad2084 100644 Binary files a/backend/data/db.sqlite and b/backend/data/db.sqlite differ diff --git a/backend/data/db.sqlite-shm b/backend/data/db.sqlite-shm index 3d2446d..41f2610 100644 Binary files a/backend/data/db.sqlite-shm and b/backend/data/db.sqlite-shm differ diff --git a/backend/data/db.sqlite-wal b/backend/data/db.sqlite-wal index 1d97cbf..53d4572 100644 Binary files a/backend/data/db.sqlite-wal and b/backend/data/db.sqlite-wal differ diff --git a/backend/data/init.sql b/backend/data/init.sql index 675cc28..841b7ff 100644 --- a/backend/data/init.sql +++ b/backend/data/init.sql @@ -5,11 +5,10 @@ create table if not exists customers ( name text check(name is null or trim(name) <> '' and length(name) < 256), email text check(email is null or trim(email) <> '' and length(email) < 128), password text check(password is null or length(password) > 7 and length(password) < 64), - telegram_user_id integer, + telegram_id integer, plan integer, json_balance text default '{}', - activation_key text, - is_active integer default 0, + is_blocked integer default 0, json_company text default '{}', upload_group_id integer, json_backup_server text default '{}', diff --git a/backend/letsgo.bat b/backend/letsgo.bat new file mode 100644 index 0000000..d831440 --- /dev/null +++ b/backend/letsgo.bat @@ -0,0 +1 @@ +node app \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index d1bef8c..26bb085 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -392,9 +392,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -1169,9 +1169,9 @@ } }, "node_modules/nodemailer": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.0.tgz", - "integrity": "sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", + "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==", "license": "MIT-0", "engines": { "node": ">=6.0.0" diff --git a/backend/public/index.html b/backend/public/index.html index 254ff81..df4399f 100644 --- a/backend/public/index.html +++ b/backend/public/index.html @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/src/components/admin/accountHelper.vue b/src/components/admin/accountHelper.vue deleted file mode 100644 index 5bde9b2..0000000 --- a/src/components/admin/accountHelper.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/components/admin/companyInfoBlock.vue b/src/components/companyInfoBlock.vue similarity index 98% rename from src/components/admin/companyInfoBlock.vue rename to src/components/companyInfoBlock.vue index ebb4812..e6ebac5 100644 --- a/src/components/admin/companyInfoBlock.vue +++ b/src/components/companyInfoBlock.vue @@ -5,7 +5,7 @@ +
+ + + + + + + {{ user.email }} + + + {{ + tgUser?.first_name + + (tgUser?.first_name && tgUser?.last_name ? ' ' : '') + + tgUser?.last_name + + !(tgUser?.first_name || tgUser?.last_name) ? tgUser?.username : '' + }} + +
+ + + + + diff --git a/src/components/admin/pnAutoAvatar.vue b/src/components/pnAutoAvatar.vue similarity index 100% rename from src/components/admin/pnAutoAvatar.vue rename to src/components/pnAutoAvatar.vue diff --git a/src/components/admin/pnImageSelector.vue b/src/components/pnImageSelector.vue similarity index 100% rename from src/components/admin/pnImageSelector.vue rename to src/components/pnImageSelector.vue diff --git a/src/components/pnMagicOverlay.vue b/src/components/pnMagicOverlay.vue new file mode 100644 index 0000000..19712b1 --- /dev/null +++ b/src/components/pnMagicOverlay.vue @@ -0,0 +1,73 @@ + + + + + + + diff --git a/src/components/admin/pnOverlay.vue b/src/components/pnOverlay.vue similarity index 100% rename from src/components/admin/pnOverlay.vue rename to src/components/pnOverlay.vue diff --git a/src/components/admin/pnPageCard.vue b/src/components/pnPageCard.vue similarity index 78% rename from src/components/admin/pnPageCard.vue rename to src/components/pnPageCard.vue index b9c056e..4db83ee 100644 --- a/src/components/admin/pnPageCard.vue +++ b/src/components/pnPageCard.vue @@ -2,7 +2,7 @@
diff --git a/src/components/admin/pnScrollList.vue b/src/components/pnScrollList.vue similarity index 100% rename from src/components/admin/pnScrollList.vue rename to src/components/pnScrollList.vue diff --git a/src/components/admin/projectInfoBlock.vue b/src/components/projectInfoBlock.vue similarity index 100% rename from src/components/admin/projectInfoBlock.vue rename to src/components/projectInfoBlock.vue diff --git a/src/i18n/en-US/index.ts b/src/i18n/en-US/index.ts index 40f68b3..2047dca 100644 --- a/src/i18n/en-US/index.ts +++ b/src/i18n/en-US/index.ts @@ -1 +1 @@ -export default { EN: 'EN', RU: 'RU', continue: 'Continue', back: 'Back', month: 'month', months: 'months', slogan: 'Work together - it\'s magic!', under_construction: 'Under construction.', login__email: 'E-mail', login__password: 'Password', login__forgot_password: 'Forgot Password?', login__sign_in: 'Log in', login__incorrect_login_data: 'User data not found. Edit your auth details before continuing', login__or_continue_as: 'or continue as', login__terms_of_use: 'Terms of use', login__accept_terms_of_use: 'I accept the', login__register: 'Create account', login__registration_message_error: 'Error', login__licensing_agreement: 'Licensing agreement', login__have_account: 'Already have an accont?', user__logout: 'Logout', projects__projects: 'Projects', projects__show_archive: 'Show archive', projects__hide_archive: 'Hide archive', projects__restore_archive_warning: 'Attention!', projects__restore_archive_warning_message: 'To restore a project from an archive, you must manually attach chats to it.', project__chats: 'Chats', project__persons: 'Persons', project__companies: 'Companies', project__edit: 'Edit', project__backup: 'Backup', project__archive: 'Archive', project__archive_warning: 'Are you sure?', project__archive_warning_message: 'Chat tracking in the project will be disabled after moving to the archive.', project__delete: 'Delete', project__delete_warning: 'Warning!', project__delete_warning_message: 'All project data will be removed. This action cannot be undone.', project_chats__search: 'Search', project_chats__send_chat: 'Request for attach chat', project_chats__send_chat_description: 'Provide instructions to the chat admin', project_chats__attach_chat: 'Attach chat', project_chats__attach_chat_description: 'Requires chat administrator privileges', project_chat__delete_warning: 'Warning!', project_chat__delete_warning_message: 'Chat tracking will be discontinued. If necessary, the cat can be attached again.', project_card__project_card: 'Project card', project_card__add_project: 'Add project', project_card__project_name: 'Name', project_card__project_description: 'Description', project_card__btn_accept: 'Accept', project_card__btn_back: 'Back', project_card__image_use_as_background_chats: 'logo as background for chats', project_card__error_name: 'Field is required', forgot_password__password_recovery: 'Password recovery', account_helper__enter_email: 'Enter account e-mail', account_helper__email: 'E-mail', account_helper__confirm_email: 'Confirm e-mail', account_helper__confirm_email_message: 'Enter the Code from e-mail to continue recover your password. If you haven\'t received an e-mail with the Code, check the Spam folder.', account_helper__code: 'Code', account_helper__code_error: 'Incorrect code. Ensure your e-mail is correct and try again.', account_helper__set_password: 'Set password', account_helper__password: 'Password', account_helper__finish: 'Finish', account_helper__finish_after_message: 'Done!', account__user_settings: 'User settings', account__your_company: 'Your company', account__change_auth_message_2: 'After creating a user, all data from the Telegram account will be transferred to the new account.', account__change_auth_btn: 'Create system account', account__change_auth_warning: 'WARNING!', account__change_auth_warning_message: 'Reverse data transfer is not possible.', account__chats: 'Chats', account__chats_active: 'Active', account__chats_unbound: 'Unbound', account__chats_free: 'Free', account__chats_total: 'Total', account__subscribe: 'Subscribe', account__subscribe_description: 'With a subscription, you can attach more active chats.', account__auth_change_method: 'Change authorization method', account__auth_change_method_description: 'In case of corporate use, it is recommended to log in with a username and password.', account__auth_change_password: 'Change account password', account__auth_change_password_description: 'Access to the email address used for system login is required.', account__auth_change_account: 'Change account e-mail', account__auth_change_account_description: 'Access to both the current and new email addresses used for system authentication is required.', account__company_data: 'Your company data', account__company_data_description: 'Projects will automatically include this data.', account__manual: 'Manual', account__manual_description: 'Go to our Telegram channel with video tutorials.', account__support: 'Support', account__support_description: 'Need help? Contact us!', account__terms_of_use: 'Terms of use', account__privacy: 'Privacy and Cookie Policy', company__mask: 'Company cloacking', mask__title_table: 'Excluded', mask__help_title: 'Cloacking', mask__help_message: 'It is possible to cloacking a company by representing its personnel as your own to companies other than those on the exclusion list.', company_info__title_card: 'Company card', company_info__name: 'Name', company_info__description: 'Description', company_info__persons: 'Persons', company_create__title_card: 'Add company', project_persons__search: 'Search', person_card__title: 'Person card', person_card__name: 'Name', person_card__company: 'Company name', person_card__department: 'Department', person_card__role: 'Role', settings__title: 'Settings', settings__language: 'Language', settings__font_size: 'Font size', terms__title: 'Terms of use', subscribe__title: 'Subscribe', subscribe__current_balance: 'Current balance', subscribe__token_formula: '1 = 1 day of access to 1 chat', subscribe__token_formula_description: 'unbound and free chats are not counted', subscribe__info: 'With a subscription, you can attach more chats. Archived chats are not counted.', subscribe__about: 'about', subscribe__select_payment_1: 'You can pay for your subscription using ', subscribe__select_payment_2: 'Telegram stars', subscribe__select_option_1: 'Telegram stars', subscribe__select_option_2: 'Telegram stars', subscribe__select_option_3: 'Telegram stars', subscribe__select_option_user: 'Telegram stars' } \ No newline at end of file +export default { EN: 'EN', RU: 'RU', continue: 'Continue', back: 'Back', month: 'month', months: 'months', slogan: 'Work together - it\'s magic!', under_construction: 'Under construction.', login__email: 'E-mail', login__password: 'Password', login__forgot_password: 'Forgot Password?', login__sign_in: 'Log in', login__incorrect_login_data: 'User data not found. Edit your auth details before continuing', login__or_continue_as: 'or continue as', login__terms_of_use: 'Terms of use', login__accept_terms_of_use: 'I accept the', login__register: 'Create account', login__registration_message_error: 'Error', login__licensing_agreement: 'Licensing agreement', login__have_account: 'Already have an accont?', login__incorrect_email: 'Please enter a valid email address', login__password_require: 'At least 8 characters', user__logout: 'Logout', projects__projects: 'Projects', projects__show_archive: 'Show archive', projects__hide_archive: 'Hide archive', projects__restore_archive_warning: 'Attention!', projects__restore_archive_warning_message: 'To restore a project from an archive, you must manually attach chats to it.', projects__lets_start: 'Create a Project', projects__lets_start_description: 'Projects isolate data: contacts, tasks, documents, and chats are visible only to members', project__chats: 'Chats', project__persons: 'Persons', project__companies: 'Companies', project__edit: 'Edit', project__backup: 'Backup', project__archive: 'Archive', project__archive_warning: 'Are you sure?', project__archive_warning_message: 'Chat tracking in the project will be disabled after moving to the archive.', project__delete: 'Delete', project__delete_warning: 'Warning!', project__delete_warning_message: 'All project data will be removed. This action cannot be undone.', project_chats__search: 'Search', project_chats__send_chat: 'Request for attach chat', project_chats__send_chat_description: 'Provide instructions to the chat admin', project_chats__attach_chat: 'Attach chat', project_chats__attach_chat_description: 'Requires chat administrator privileges', project_chat__delete_warning: 'Warning!', project_chat__delete_warning_message: 'Chat tracking will be discontinued. If necessary, the cat can be attached again.', project_card__project_card: 'Project card', project_card__add_project: 'Add project', project_card__project_name: 'Name', project_card__project_description: 'Description', project_card__btn_accept: 'Accept', project_card__btn_back: 'Back', project_card__image_use_as_background_chats: 'logo as background for chats', project_card__error_name: 'Field is required', forgot_password__password_recovery: 'Password recovery', account_helper__enter_email: 'Enter account e-mail', account_helper__email: 'E-mail', account_helper__confirm_email: 'Confirm e-mail', account_helper__confirm_email_message: 'Enter the Code from e-mail to continue recover your password. If you haven\'t received an e-mail with the Code, check the Spam folder.', account_helper__code: 'Code', account_helper__code_error: 'Incorrect code. Ensure your e-mail is correct and try again.', account_helper__set_password: 'Set password', account_helper__password: 'Password', account_helper__finish: 'Finish', account_helper__finish_after_message: 'Done!', account__user_settings: 'User settings', account__your_company: 'Your company', account__change_auth_message_2: 'After creating a user, all data from the Telegram account will be transferred to the new account.', account__change_auth_btn: 'Create system account', account__change_auth_warning: 'WARNING!', account__change_auth_warning_message: 'Reverse data transfer is not possible.', account__chats: 'Chats', account__chats_active: 'Active', account__chats_unbound: 'Unbound', account__chats_free: 'Free', account__chats_total: 'Total', account__subscribe: 'Subscribe', account__subscribe_description: 'With a subscription, you can attach more active chats.', account__auth_change_method: 'Change authorization method', account__auth_change_method_description: 'In case of corporate use, it is recommended to log in with a username and password.', account__auth_change_password: 'Change account password', account__auth_change_password_description: 'Access to the email address used for system login is required.', account__auth_change_account: 'Change account e-mail', account__auth_change_account_description: 'Access to both the current and new email addresses used for system authentication is required.', account__company_data: 'Your company data', account__company_data_description: 'Projects will automatically include this data.', account__manual: 'Manual', account__manual_description: 'Go to our Telegram channel with video tutorials.', account__support: 'Support', account__support_description: 'Need help? Contact us!', account__terms_of_use: 'Terms of use', account__privacy: 'Privacy and Cookie Policy', company__mask: 'Company cloacking', mask__title_table: 'Excluded', mask__help_title: 'Cloacking', mask__help_message: 'It is possible to cloacking a company by representing its personnel as your own to companies other than those on the exclusion list.', company_info__title_card: 'Company card', company_info__name: 'Name', company_info__description: 'Description', company_info__persons: 'Persons', company_create__title_card: 'Add company', project_persons__search: 'Search', person_card__title: 'Person card', person_card__name: 'Name', person_card__company: 'Company name', person_card__department: 'Department', person_card__role: 'Role', settings__title: 'Settings', settings__language: 'Language', settings__font_size: 'Font size', terms__title: 'Terms of use', subscribe__title: 'Subscribe', subscribe__current_balance: 'Current balance', subscribe__token_formula: '1 = 1 day of access to 1 chat', subscribe__token_formula_description: 'unbound and free chats are not counted', subscribe__info: 'With a subscription, you can attach more chats. Archived chats are not counted.', subscribe__about: 'about', subscribe__select_payment_1: 'You can pay for your subscription using ', subscribe__select_payment_2: 'Telegram stars', subscribe__select_option_1: 'Telegram stars', subscribe__select_option_2: 'Telegram stars', subscribe__select_option_3: 'Telegram stars', subscribe__select_option_user: 'Telegram stars' } \ No newline at end of file diff --git a/src/i18n/ru-RU/index.ts b/src/i18n/ru-RU/index.ts index e3dd6da..f88fd31 100644 --- a/src/i18n/ru-RU/index.ts +++ b/src/i18n/ru-RU/index.ts @@ -1 +1 @@ -export default { EN: 'EN', RU: 'RU', continue: 'Продолжить', back: 'Назад', month: 'мес.', months: 'мес.', slogan: 'Работайте вместе - это волшебство!', under_construction: 'В разработке.', login__email: 'Электронная почта', login__password: 'Пароль', login__forgot_password: 'Забыли пароль?', login__sign_in: 'Войти', login__incorrect_login_data: 'Пользователь с такими данными не найден. Отредактируйте введенные данные', login__or_continue_as: 'или продолжить', login__terms_of_use: 'Пользовательское соглашение', login__accept_terms_of_use: 'Я принимаю', login__register: 'Зарегестрироваться', login__registration_message_error: 'Ошибка', login__licensing_agreement: 'Договор о лицензировании', login__have_account: 'Есть учетная запись', user__logout: 'Выход', projects__projects: 'Проекты', projects__show_archive: 'Показать архив', projects__hide_archive: 'Скрыть архив', projects__restore_archive_warning: 'Внимание!', projects__restore_archive_warning_message: 'При восстановлении проекта из архива - присоединение чатов к проекту требуется осуществлять вручную.', project__chats: 'Чаты', project__persons: 'Люди', project__companies: 'Компании', project__edit: 'Редактировать', project__backup: 'Резервная копия', project__archive: 'В архив', project__archive_warning: 'Вы уверены?', project__archive_warning_message: 'После перемещения проекта в архив отслеживание чатов будет отключено.', project__delete: 'Удалить', project__delete_warning: 'Внимание!', project__delete_warning_message: 'Все данные проекта будут безвозвратно удалены.', project_chats__search: 'Поиск', project_chats__send_chat: 'Запрос на добавление чата', project_chats__send_chat_description: 'Отправить инструкцию администратору чата', project_chats__attach_chat: 'Добавить чат', project_chats__attach_chat_description: 'Необходимы права администратора чата', project_chat__delete_warning: 'Внимание!', project_chat__delete_warning_message: 'Отслеживание чата будет прекращено. При необходимости чат можно будет подключить снова.', project_card__project_card: 'Карточка компании', project_card__add_project: 'Новый проект', project_card__project_name: 'Название', project_card__project_description: 'Описание', project_card__btn_accept: 'Подтвердить', project_card__btn_back: 'Назад', project_card__image_use_as_background_chats: 'логотип в качестве фона для чатов', project_card__error_name: 'Поле обязательно к заполнению', forgot_password__password_recovery: 'Восстановление пароля', account_helper__enter_email: 'Введите электронную почту', account_helper__email: 'Электронная почта', account_helper__confirm_email: 'Подтверждение электронной почты', account_helper__confirm_email_message: 'Введите код из письма для продолжения восстановления пароля. Если не получили письмо с кодом - проверьте папку Спам', account_helper__code: 'Код', account_helper__code_error: 'Был введен неверный код. Проверьте адрес электронной почты и повторите попытку.', account_helper__set_password: 'Установка пароля', account_helper__password: 'Пароль', account_helper__finish: 'Отправить', account_helper__finish_after_message: 'Готово!', account__user_settings: 'Пользовательские настройки', account__your_company: 'Ваша компания', account__change_auth_message_2: 'После создания пользователя все данные с учетной записи Telegram будут перенесены на новую учетную запись.', account__change_auth_btn: 'Создать пользователя', account__change_auth_warning: 'ВНИМАНИЕ!', account__change_auth_warning_message: 'Обратный перенос данных не возможен.', account__chats: 'Чаты', account__chats_active: 'Активные', account__chats_unbound: 'Открепленные', account__chats_free: 'Бесплатные', account__chats_total: 'Всего', account__subscribe: 'Подписка', account__subscribe_description: 'С помощью подписки можно подключить дополнительные чаты.', account__auth_change_method: 'Сменить способ авторизации', account__auth_change_method_description: 'В случае корпоративного использования рекомендуется входить в систему, указав логин и пароль.', account__auth_change_password: 'Изменить пользовательский пароль', account__auth_change_password_description: 'Необходим доступ к электронной почте, используемой для входа в систему.', account__auth_change_account: 'Сменить электронную почту учетной записи', account__auth_change_account_description: 'Необходим доступ к текущей и новой электронной почте, используемым для входа в систему.', account__company_data: 'Данные вашей компании', account__company_data_description: 'Эти данные будут автоматически подгружаться в проекты. ', account__manual: 'Инструкции', account__manual_description: 'Перейдите в наш Telegram-канал с обучающими видеороликами.', account__support: 'Поддержка', account__support_description: 'Есть вопросы - напишите нам!', account__terms_of_use: 'Пользовательское соглашение', account__privacy: 'Политика конфидециальности', company__mask: 'Маскировка компаний', mask__title_table: 'Исключения', mask__help_title: 'Маскировка', mask__help_message: 'Возможно замаскировать компанию, представляя ее персонал как собственный для других компаний, кроме тех, что есть в перечне исключений. ', company_info__title_card: 'Карточка компании', company_info__name: 'Название', company_info__description: 'Описание', company_info__persons: 'Сотрудники', company_create__title_card: 'Добавление компании', project_persons__search: 'Поиск', person_card__title: 'Карточка сотрудника', person_card__name: 'ФИО', person_card__company: 'Название компании', person_card__department: 'Подразделение', person_card__role: 'Функционал (должность)', settings__title: 'Настройки', settings__language: 'Язык', settings__font_size: 'Размер шрифта', terms__title: 'Пользовательское соглашение', subscribe__title: 'Подписка', subscribe__current_balance: 'Текущий баланс', subscribe__token_formula: '1 = 1 день подключения к 1 чату', subscribe__token_formula_description: 'отвязанные и бесплатные чаты не учитываются', subscribe__info: 'С помощью подписки можно подключить к бесплатным групповым чатам дополнительные. Архивные чаты не учитываются. ', subscribe__about: 'около', subscribe__select_payment_1: 'Вы можете оплатить подписку с помощью', subscribe__select_payment_2: 'Telegram stars', subscribe__select_option_1: 'Telegram stars', subscribe__select_option_2: 'Telegram stars', subscribe__select_option_3: 'Telegram stars', subscribe__select_option_user: 'Telegram stars' } \ No newline at end of file +export default { EN: 'EN', RU: 'RU', continue: 'Продолжить', back: 'Назад', month: 'мес.', months: 'мес.', slogan: 'Работайте вместе - это волшебство!', under_construction: 'В разработке.', login__email: 'Электронная почта', login__password: 'Пароль', login__forgot_password: 'Забыли пароль?', login__sign_in: 'Войти', login__incorrect_login_data: 'Пользователь с такими данными не найден. Отредактируйте введенные данные', login__or_continue_as: 'или продолжить', login__terms_of_use: 'Пользовательское соглашение', login__accept_terms_of_use: 'Я принимаю', login__register: 'Зарегестрироваться', login__registration_message_error: 'Ошибка', login__licensing_agreement: 'Договор о лицензировании', login__have_account: 'Есть учетная запись', login__incorrect_email: 'Адрес почты некорректный', login__password_require: 'Мин. 8 символов', user__logout: 'Выход', projects__projects: 'Проекты', projects__show_archive: 'Показать архив', projects__hide_archive: 'Скрыть архив', projects__restore_archive_warning: 'Внимание!', projects__restore_archive_warning_message: 'При восстановлении проекта из архива - присоединение чатов к проекту требуется осуществлять вручную.', projects__lets_start: 'Создайте проект', projects__lets_start_description: 'Проекты помогают изолировать данные: контакты, задачи, документы и чаты доступны только участникам', project__chats: 'Чаты', project__persons: 'Люди', project__companies: 'Компании', project__edit: 'Редактировать', project__backup: 'Резервная копия', project__archive: 'В архив', project__archive_warning: 'Вы уверены?', project__archive_warning_message: 'После перемещения проекта в архив отслеживание чатов будет отключено.', project__delete: 'Удалить', project__delete_warning: 'Внимание!', project__delete_warning_message: 'Все данные проекта будут безвозвратно удалены.', project_chats__search: 'Поиск', project_chats__send_chat: 'Запрос на добавление чата', project_chats__send_chat_description: 'Отправить инструкцию администратору чата', project_chats__attach_chat: 'Добавить чат', project_chats__attach_chat_description: 'Необходимы права администратора чата', project_chat__delete_warning: 'Внимание!', project_chat__delete_warning_message: 'Отслеживание чата будет прекращено. При необходимости чат можно будет подключить снова.', project_card__project_card: 'Карточка компании', project_card__add_project: 'Новый проект', project_card__project_name: 'Название', project_card__project_description: 'Описание', project_card__btn_accept: 'Подтвердить', project_card__btn_back: 'Назад', project_card__image_use_as_background_chats: 'логотип в качестве фона для чатов', project_card__error_name: 'Поле обязательно к заполнению', forgot_password__password_recovery: 'Восстановление пароля', account_helper__enter_email: 'Введите электронную почту', account_helper__email: 'Электронная почта', account_helper__confirm_email: 'Подтверждение электронной почты', account_helper__confirm_email_message: 'Введите код из письма для продолжения восстановления пароля. Если не получили письмо с кодом - проверьте папку Спам', account_helper__code: 'Код', account_helper__code_error: 'Был введен неверный код. Проверьте адрес электронной почты и повторите попытку.', account_helper__set_password: 'Установка пароля', account_helper__password: 'Пароль', account_helper__finish: 'Отправить', account_helper__finish_after_message: 'Готово!', account__user_settings: 'Пользовательские настройки', account__your_company: 'Ваша компания', account__change_auth_message_2: 'После создания пользователя все данные с учетной записи Telegram будут перенесены на новую учетную запись.', account__change_auth_btn: 'Создать пользователя', account__change_auth_warning: 'ВНИМАНИЕ!', account__change_auth_warning_message: 'Обратный перенос данных не возможен.', account__chats: 'Чаты', account__chats_active: 'Активные', account__chats_unbound: 'Открепленные', account__chats_free: 'Бесплатные', account__chats_total: 'Всего', account__subscribe: 'Подписка', account__subscribe_description: 'С помощью подписки можно подключить дополнительные чаты.', account__auth_change_method: 'Сменить способ авторизации', account__auth_change_method_description: 'В случае корпоративного использования рекомендуется входить в систему, указав логин и пароль.', account__auth_change_password: 'Изменить пользовательский пароль', account__auth_change_password_description: 'Необходим доступ к электронной почте, используемой для входа в систему.', account__auth_change_account: 'Сменить электронную почту учетной записи', account__auth_change_account_description: 'Необходим доступ к текущей и новой электронной почте, используемым для входа в систему.', account__company_data: 'Данные вашей компании', account__company_data_description: 'Эти данные будут автоматически подгружаться в проекты. ', account__manual: 'Инструкции', account__manual_description: 'Перейдите в наш Telegram-канал с обучающими видеороликами.', account__support: 'Поддержка', account__support_description: 'Есть вопросы - напишите нам!', account__terms_of_use: 'Пользовательское соглашение', account__privacy: 'Политика конфидециальности', company__mask: 'Маскировка компаний', mask__title_table: 'Исключения', mask__help_title: 'Маскировка', mask__help_message: 'Возможно замаскировать компанию, представляя ее персонал как собственный для других компаний, кроме тех, что есть в перечне исключений. ', company_info__title_card: 'Карточка компании', company_info__name: 'Название', company_info__description: 'Описание', company_info__persons: 'Сотрудники', company_create__title_card: 'Добавление компании', project_persons__search: 'Поиск', person_card__title: 'Карточка сотрудника', person_card__name: 'ФИО', person_card__company: 'Название компании', person_card__department: 'Подразделение', person_card__role: 'Функционал (должность)', settings__title: 'Настройки', settings__language: 'Язык', settings__font_size: 'Размер шрифта', terms__title: 'Пользовательское соглашение', subscribe__title: 'Подписка', subscribe__current_balance: 'Текущий баланс', subscribe__token_formula: '1 = 1 день подключения к 1 чату', subscribe__token_formula_description: 'отвязанные и бесплатные чаты не учитываются', subscribe__info: 'С помощью подписки можно подключить к бесплатным групповым чатам дополнительные. Архивные чаты не учитываются. ', subscribe__about: 'около', subscribe__select_payment_1: 'Вы можете оплатить подписку с помощью', subscribe__select_payment_2: 'Telegram stars', subscribe__select_option_1: 'Telegram stars', subscribe__select_option_2: 'Telegram stars', subscribe__select_option_3: 'Telegram stars', subscribe__select_option_user: 'Telegram stars' } \ No newline at end of file diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 40a112d..9761357 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -33,7 +33,7 @@ diff --git a/src/pages/AccountChangePasswordPage.vue b/src/pages/AccountChangePasswordPage.vue index 73d4a21..da72526 100644 --- a/src/pages/AccountChangePasswordPage.vue +++ b/src/pages/AccountChangePasswordPage.vue @@ -12,6 +12,6 @@ diff --git a/src/pages/AccountCreatePage.vue b/src/pages/AccountCreatePage.vue index 38ee95c..4e13958 100644 --- a/src/pages/AccountCreatePage.vue +++ b/src/pages/AccountCreatePage.vue @@ -6,12 +6,20 @@
- + diff --git a/src/pages/AccountForgotPasswordPage.vue b/src/pages/AccountForgotPasswordPage.vue index 8a71e0b..a4b94b5 100644 --- a/src/pages/AccountForgotPasswordPage.vue +++ b/src/pages/AccountForgotPasswordPage.vue @@ -6,17 +6,20 @@ - + diff --git a/src/pages/AccountPage.vue b/src/pages/AccountPage.vue index 2b0f59c..8825892 100644 --- a/src/pages/AccountPage.vue +++ b/src/pages/AccountPage.vue @@ -1,25 +1,16 @@ diff --git a/src/pages/SubscribePage.vue b/src/pages/SubscribePage.vue index 6db5ca0..d693745 100644 --- a/src/pages/SubscribePage.vue +++ b/src/pages/SubscribePage.vue @@ -46,11 +46,11 @@