diff --git a/actions/adminActions.js b/actions/adminActions.js index fe4cb87..1a8e7d7 100644 --- a/actions/adminActions.js +++ b/actions/adminActions.js @@ -41,30 +41,30 @@ export const sendInvite = ({ name, email, companies }) => { console.log("ACTION", "sendInvite()", "response.data", response.data); - resolve(); + resolve(response.data); }) .catch((error) => { console.error("ACTION", "sendInvite()", "error"); - console.error(error); + console.log("error.response.data", error.response.data); - reject(); + reject(error.response.data); }); }); } -export const removeUser = ({ email }) => +export const removeUser = ({ account, emails }) => { - console.log("ACTION", "removeUser()", { email }); + console.log("ACTION", "removeUser()", { account, emails }); return new Promise((resolve, reject) => { - axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/admin/remove`, { email }) + axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/admin/remove`, { account, emails }) .then(async (response) => { console.log("ACTION", "removeUser()", "response.data", response.data); - resolve(); + resolve(response.data); }) .catch((error) => { diff --git a/pages/api/admin/index.js b/pages/api/admin/index.js index f3ff5a6..c27feed 100644 --- a/pages/api/admin/index.js +++ b/pages/api/admin/index.js @@ -41,7 +41,7 @@ export default async function handler(req, res) console.error(error); res.status(403).json(); - }); + }); } else { diff --git a/pages/api/admin/invite.js b/pages/api/admin/invite.js index 75a4a76..ef11c2b 100644 --- a/pages/api/admin/invite.js +++ b/pages/api/admin/invite.js @@ -4,9 +4,16 @@ import { Cookies } from 'react-cookie'; import cookie from 'cookie'; import moment from 'moment'; import jwt from 'jsonwebtoken'; +import { inspect } from 'util'; import { cors } from '../../../lib/cors'; +const validateEmail = (email) => { + return email.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,}))$/ + ); +}; + export default async function handler(req, res) { await cors(req, res); @@ -28,32 +35,53 @@ export default async function handler(req, res) const admin_companies = client_jwt_decoded.companies; const allowed_companies = []; - if(admin_companies !== undefined && admin_companies !== null) + if(validateEmail(email)) { - if(companies !== undefined && companies !== null) + if(admin_companies !== undefined && admin_companies !== null) { - for(let c in companies) + if(companies !== undefined && companies !== null) { - for(let ac in admin_companies) + for(let c in companies) { - if(admin_companies[ac].acc_number === companies[c]) + for(let ac in admin_companies) { - allowed_companies.push(companies[c]); + if(admin_companies[ac].acc_number === companies[c]) + { + allowed_companies.push(companies[c]); + } } } - } - if(allowed_companies.length > 0) - { - const payload = { name, email, companies, }; - console.log("payload"); - console.log(payload); + if(allowed_companies.length > 0) + { + const payload = { name, email, companies, }; + console.log("payload"); + console.log(payload); - const crm_jwt = jwt.sign(payload, process.env.JWT_SECRET_CRM, { noTimestamp: true }); + const crm_jwt_token = jwt.sign(payload, process.env.JWT_SECRET_CRM, { noTimestamp: true }); - res.status(200).send({ - status: "success", - }); + await axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/admin/invite/`, { + token: crm_jwt_token, + }) + .then((api_response) => + { + console.log("API", "auth/invite", "RESPONSE"); + console.log(inspect(api_response.data, true, null, true)); + + res.status(200).send(api_response.data); + }) + .catch((error) => + { + console.error("API", "auth/invite", "error"); + console.error(error); + + res.status(403).json(); + }); + } + else + { + res.status(403).json(); + } } else { @@ -67,7 +95,7 @@ export default async function handler(req, res) } else { - res.status(403).json(); + res.status(400).json({ errors: [ "email" ]}); } } else diff --git a/pages/api/admin/remove.js b/pages/api/admin/remove.js index fa72bd5..f102652 100644 --- a/pages/api/admin/remove.js +++ b/pages/api/admin/remove.js @@ -4,13 +4,14 @@ import { Cookies } from 'react-cookie'; import cookie from 'cookie'; import moment from 'moment'; import jwt from 'jsonwebtoken'; +import { inspect } from 'util'; import { cors } from '../../../lib/cors'; export default async function handler(req, res) { await cors(req, res); - let { email } = req.body; + let { emails } = req.body; console.log("API", "admin/remove"); if(req.headers.cookie !== undefined) @@ -19,8 +20,32 @@ export default async function handler(req, res) if(cookies.jwt !== undefined && cookies.jwt !== null) { - res.status(200).send({ - status: "success", + let client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT); + console.log("API", "admin/remove", "client_jwt_decoded", client_jwt_decoded); + + const payload = { + acc_number: client_jwt_decoded.acc_number, + emails, + }; + + const crm_jwt_token = jwt.sign(payload, process.env.JWT_SECRET_CRM, { noTimestamp: true }); + + await axios.post(`${ process.env.NEXT_PUBLIC_API_HOST }/api/admin/remove/`, { + token: crm_jwt_token, + }) + .then((api_response) => + { + console.log("API", "auth/remove", "RESPONSE"); + console.log(inspect(api_response.data, true, null, true)); + + res.status(200).send(api_response.data); + }) + .catch((error) => + { + console.error("API", "auth/remove", "error"); + console.error(error); + + res.status(403).json(); }); } else diff --git a/pages/api/auth/switch.js b/pages/api/auth/switch.js index 487a5ab..2d11bc0 100644 --- a/pages/api/auth/switch.js +++ b/pages/api/auth/switch.js @@ -43,10 +43,11 @@ export default async function handler(req, res) { const new_client_jwt = jwt.sign({ acc_number: acc_number, + is_admin: company.is_admin, login: client_jwt_decoded.login, companies: client_jwt_decoded.companies, }, process.env.JWT_SECRET_CLIENT, { noTimestamp: true }); - + res.status(200).send({ status: "success", token: new_client_jwt, diff --git a/pages/settings/admin.js b/pages/settings/admin.js index 4dccb11..6c2860d 100644 --- a/pages/settings/admin.js +++ b/pages/settings/admin.js @@ -34,6 +34,17 @@ class Form extends React.Component }; } + componentDidMount() + { + const { errors } = this.props; + + if(errors.length > 0) + { + const update = { ...this.state, ...this.props.form }; + this.setState(update); + } + } + _handle_onChange = (field, value) => { this.setState({ [ field ]: value }, () => @@ -109,16 +120,16 @@ class Form extends React.Component render() { - const { companies } = this.props; + const { companies, errors } = this.props; const { name, email, selection, selected_companies_all, selected_companies_list, } = this.state; return (
- { this._handle_onChange("name", event.target.value) } }/> + -1 ? { color: "#ED0A34" } : {} } onChange={ (event) => { this._handle_onChange("name", event.target.value) } }/>
- { this._handle_onChange("email", event.target.value) } }/> + -1 ? { color: "#ED0A34" } : {} } onChange={ (event) => { this._handle_onChange("email", event.target.value) } }/>
Пользователь
@@ -178,15 +189,19 @@ class AdminPage extends React.Component users: null, companies: null, add: false, - edit: false, + edit: false, save: false, - form: {}, + form: {}, + observer: false, + to_delete: [], + errors: [], }; } static getDerivedStateFromProps(nextProps, prevState) { return { + observer: nextProps.observer, user: nextProps.user, users: nextProps.users, companies: nextProps.companies, @@ -197,15 +212,22 @@ class AdminPage extends React.Component { this.setState({ loading: true }, () => { - getUsers({ dispatch: this.props.dispatch }) - .then(() => + if(!this.state.observer && !this.state.user.is_admin) { - this.setState({ loading: false, }) - }) - .catch(() => + this.props.router.push("/"); + } + else { - - }); + getUsers({ dispatch: this.props.dispatch }) + .then(() => + { + this.setState({ loading: false, }) + }) + .catch(() => + { + this.setState({ loading: false }); + }); + } }); } @@ -221,40 +243,85 @@ class AdminPage extends React.Component _handle_onSave = () => { - const { form } = this.state; - const { name, email, selected_companies_list } = form; - console.log("form"); - console.log(form); + const { form, add, edit, to_delete } = this.state; - const companies = []; - for(let i in selected_companies_list) + if(add) { - companies.push(selected_companies_list[i].acc_number); - } + const { name, email, selected_companies_list } = form; - this.setState({ add: false, edit: false, loading: true }, () => - { - sendInvite({ name, email, companies }) - .then(() => + const companies = []; + for(let i in selected_companies_list) { - this.setState({ loading: false }); - }) - .catch(() => + companies.push(selected_companies_list[i].acc_number); + } + + this.setState({ add: false, edit: false, loading: true }, () => { - this.setState({ loading: false }); + sendInvite({ name, email, companies }) + .then((result) => + { + if(result.status === "success") + { + getUsers({ dispatch: this.props.dispatch }) + .then(() => + { + this.setState({ loading: false, }) + }) + .catch(() => + { + this.setState({ loading: false }); + }); + } + else + { + this.setState({ loading: false }); + } + }) + .catch((error) => + { + this.setState({ loading: false, add: true, errors: error.errors }); + }); }); - }); + } + else + { + this.setState({ add: false, edit: false, loading: true }, () => + { + removeUser({ emails: to_delete }) + .then((result) => + { + if(result.status === "success") + { + getUsers({ dispatch: this.props.dispatch }) + .then(() => + { + this.setState({ loading: false, to_delete: [] }) + }) + .catch(() => + { + this.setState({ loading: false, to_delete: [] }); + }); + } + else + { + this.setState({ loading: false }); + } + }) + .catch(() => + { + this.setState({ loading: false }); + }); + }); + } } _handle_onCancel = () => { - this.setState({ add: false, edit: false }); + this.setState({ add: false, edit: false, to_delete: [], }); } _onFormEdit = (form) => { - console.log("_onFormEdit", form); - let save = true; if(form.name === "") { @@ -272,22 +339,29 @@ class AdminPage extends React.Component } } - this.setState({ form, save }); + this.setState({ form, save, errors: [] }); + } + + _handle_onMarkToDelete = (email) => + { + const to_delete = [ ...this.state.to_delete ]; + + if(to_delete.indexOf(email) > -1) + { + + to_delete.splice(to_delete.indexOf(email), 1); + } + else + { + to_delete.push(email); + } + + this.setState({ to_delete }); } render() { - const { loading, user, users, companies, add, edit, save } = this.state; - console.log("users"); - console.log(users); - - console.log(".".repeat(100)); - console.log("user"); - console.log(user); - - console.log(".".repeat(100)); - console.log("companies"); - console.log(companies); + const { loading, user, observer, users, companies, errors, form, add, edit, save, to_delete } = this.state; return ( @@ -307,7 +381,7 @@ class AdminPage extends React.Component
- +
{ loading ? (
@@ -321,7 +395,7 @@ class AdminPage extends React.Component { add || edit ? ( <> - + ) : ( <> @@ -349,10 +423,10 @@ class AdminPage extends React.Component return (
{ entry.name } (Вы)
-
{ entry.email }
-
Администратор
+
{ entry.email } [{user.email}]
+
{ entry.is_admin ? "Администратор" : "Пользователь" }
Все организации
-
Активен
+
{ entry.is_admin ? "Активен" : entry.last !== null ? "Активен" : "Приглашен" }
{ edit && (
) } @@ -366,17 +440,17 @@ class AdminPage extends React.Component if(entry.email !== user.email) { return ( -
-
{ entry.name }
-
{ entry.email }
-
Администратор
+
-1 ? { backgroundColor: "#eee" } : {} }> +
-1 ? { textDecoration: "line-through" } : {} }>{ entry.name }
+
-1 ? { textDecoration: "line-through" } : {} }>{ entry.email }
+
-1 ? { textDecoration: "line-through" } : {} }>{ entry.is_admin ? "Администратор" : "Пользователь" }
{ entry.companies.map((company, c_index) => ( -

{ company.title }

+

-1 ? { textDecoration: "line-through" } : {} }>{ company.title }

)) }
-
Активен
+
-1 ? { textDecoration: "line-through" } : {} }>{ entry.is_admin ? "Активен" : entry.last !== null ? "Активен" : "Приглашен" }
{ edit && (
- +
) }
@@ -410,7 +484,7 @@ class AdminPage extends React.Component
{*/} { add && ( -
+ ) } {/*} {*/} @@ -429,6 +503,7 @@ class AdminPage extends React.Component function mapStateToProps(state, ownProps) { return { + observer: state.auth.observer, user: state.user, users: state.admin.users, companies: state.companies.list, diff --git a/pages/settings/components/InnerMenu/index.js b/pages/settings/components/InnerMenu/index.js index 43be922..3e89123 100644 --- a/pages/settings/components/InnerMenu/index.js +++ b/pages/settings/components/InnerMenu/index.js @@ -2,9 +2,9 @@ import React from "react"; import Link from "next/link"; const menu = [ - {id: 1, name: "Номер телефона", link: "/settings/phone"}, - {id: 2, name: "Пароль", link: "/settings/password"}, - {id: 3, name: "Настройки доступа", link: "/settings/admin"}, + {id: 1, type: "phone", name: "Номер телефона", link: "/settings/phone"}, + {id: 2, type: "password", name: "Пароль", link: "/settings/password"}, + {id: 3, type: "admin", name: "Настройки доступа", link: "/settings/admin"}, ] export default class InnerMenu extends React.Component @@ -47,19 +47,26 @@ export default class InnerMenu extends React.Component render() { + const { user, observer } = this.props; + return ( ) diff --git a/pages/settings/password.js b/pages/settings/password.js index 673513a..0a3eb8a 100644 --- a/pages/settings/password.js +++ b/pages/settings/password.js @@ -34,12 +34,14 @@ class IndexPage extends React.Component new_password_submit_disabled: true, new_password_error: false, user: {}, + observer: false, }; } static getDerivedStateFromProps(nextProps, prevState) { return { + observer: nextProps.observer, user: nextProps.user, }; } @@ -127,7 +129,7 @@ class IndexPage extends React.Component render() { console.log("this.state.user", this.state.user); - const { password, password_error, new_password, new_password_repeat, new_password_submit_disabled, new_password_check_loading, new_password_error, password_form_step } = this.state; + const { user, observer, password, password_error, new_password, new_password_repeat, new_password_submit_disabled, new_password_check_loading, new_password_error, password_form_step } = this.state; return ( @@ -147,7 +149,7 @@ class IndexPage extends React.Component
- +
{ password_form_step === 1 && (
@@ -193,6 +195,7 @@ class IndexPage extends React.Component function mapStateToProps(state, ownProps) { return { + observer: state.auth.observer, user: state.user, } } diff --git a/pages/settings/phone.js b/pages/settings/phone.js index 60349f3..f149efa 100644 --- a/pages/settings/phone.js +++ b/pages/settings/phone.js @@ -40,12 +40,14 @@ class IndexPage extends React.Component phone_check_loading: false, code_check_loading: false, user: {}, + observer: false, }; } static getDerivedStateFromProps(nextProps, prevState) { return { + observer: nextProps.observer, user: nextProps.user, }; } @@ -174,7 +176,7 @@ class IndexPage extends React.Component
- +
{ phone_form_step !== 2 && phone_form_step !== 3 && ( <> @@ -243,6 +245,7 @@ class IndexPage extends React.Component function mapStateToProps(state, ownProps) { return { + observer: state.auth.observer, user: state.user, } }