HM-85. Внедрена авторизация на сайт (#44)

This commit is contained in:
Nikolay
2020-08-02 00:56:37 +03:00
committed by GitHub
parent edc493f0a2
commit 728e530d3d
12 changed files with 90 additions and 66 deletions

View File

@ -33,10 +33,18 @@ class AuthServiceApi {
*/ */
refresh = () => { refresh = () => {
const refresh_token = tokenApi.getRefreshToken(); const refresh_token = tokenApi.getRefreshToken();
return axios.post(`${this.URL}${AUTH_ENDPOINTS.REFRESH}`, {refresh_token}) if (refresh_token) {
return axios.post(`${this.URL}${AUTH_ENDPOINTS.REFRESH}`, {refresh_token})
.then(({data: tokens}) => { .then(({data: tokens}) => {
tokenApi.saveTokenPair(tokens); tokenApi.saveTokenPair(tokens);
})
.catch((e) => {
tokenApi.clearTokents();
throw e;
}); });
}
return Promise.reject(new Error('Не авторизован'));
} }
} }

View File

@ -26,64 +26,64 @@ class HttpApi {
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object} body - тело запроса * @param {Object} body - тело запроса
*/ */
request = (method, url, body) => { request = (method, url, body, config) => {
return httpAuthApi.request({method, url, body}); return httpAuthApi.request({...config, method, url, body});
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object<string, string>} query - параметры для передачи через query * @param {Object<string, string>} query - параметры для передачи через query
*/ */
get = (url, query) => { get = (url, query, config) => {
return this.request(GET, makeUrlWithQuery(url, query)); return this.request(GET, makeUrlWithQuery(url, query), null, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object} body - тело запроса * @param {Object} body - тело запроса
*/ */
post = (url, body) => { post = (url, body, config) => {
return this.request(POST, url, body); return this.request(POST, url, body, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object} body - тело запроса * @param {Object} body - тело запроса
*/ */
put = (url, body) => { put = (url, body, config) => {
return this.request(PUT, url, body); return this.request(PUT, url, body, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object<string, string>} query - параметры для передачи через query * @param {Object<string, string>} query - параметры для передачи через query
*/ */
delete = (url, query) => { delete = (url, query, config) => {
return this.request(DELETE, makeUrlWithQuery(url, query)); return this.request(DELETE, makeUrlWithQuery(url, query), null, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object<string, string>} query - параметры для передачи через query * @param {Object<string, string>} query - параметры для передачи через query
*/ */
head = (url, query) => { head = (url, query, config) => {
return this.request(HEAD, makeUrlWithQuery(url, query)); return this.request(HEAD, makeUrlWithQuery(url, query), null, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object<string, string>} query - параметры для передачи через query * @param {Object<string, string>} query - параметры для передачи через query
*/ */
options = (url, query) => { options = (url, query, config) => {
return this.request(OPTIONS, makeUrlWithQuery(url, query)); return this.request(OPTIONS, makeUrlWithQuery(url, query), null, config);
} }
/** /**
* @param {string} url - адрес запроса * @param {string} url - адрес запроса
* @param {Object} body - тело запроса * @param {Object} body - тело запроса
*/ */
path = (url, body) => { path = (url, body, config) => {
return this.request(PATH, url, body); return this.request(PATH, url, body, config);
} }
} }

View File

@ -90,6 +90,7 @@ class HttpAuthApi {
addTokenToRequest = (requestConfig) => ({ addTokenToRequest = (requestConfig) => ({
...requestConfig, ...requestConfig,
headers: { headers: {
...(requestConfig.headers ?? {}),
'Authorization': tokenApi.getAccessToken(), 'Authorization': tokenApi.getAccessToken(),
}, },
}) })

View File

@ -16,7 +16,7 @@ class LocalStorageAPI {
* Возвращает распарсенный объект из Local Storage по ключу из конструктора * Возвращает распарсенный объект из Local Storage по ключу из конструктора
*/ */
request () { request () {
const value = this.api.getItem(this.key) || '{}'; const value = this.api.getItem(this.key) || 'null';
return JSON.parse(value); return JSON.parse(value);
} }

View File

@ -1,6 +1,6 @@
import axios from 'axios';
import {ENDPOINTS} from './consts'; import {ENDPOINTS} from './consts';
import adminConfigsService from '../services/AdminConfigsService'; import adminConfigsService from '../services/AdminConfigsService';
import http from './HttpAPI';
class StorageLogsApi { class StorageLogsApi {
constructor () { constructor () {
@ -9,22 +9,22 @@ class StorageLogsApi {
} }
requestServerLogs = async () => { requestServerLogs = async () => {
const {data} = await axios.get(`${this.URL}${ENDPOINTS.SERVER_LOGS}`); const {data} = await http.get(`${this.URL}${ENDPOINTS.SERVER_LOGS}`);
return data; return data;
} }
requestClientLogs = async () => { requestClientLogs = async () => {
const {data} = await axios.get(`${this.URL}${ENDPOINTS.CLIENT_LOGS}`); const {data} = await http.get(`${this.URL}${ENDPOINTS.CLIENT_LOGS}`);
return data; return data;
} }
deleteAllServerLogs = async () => { deleteAllServerLogs = async () => {
const {data} = await axios.delete(`${this.URL}${ENDPOINTS.SERVER_LOGS}`); const {data} = await http.delete(`${this.URL}${ENDPOINTS.SERVER_LOGS}`);
return data; return data;
} }
deleteAllClientLogs = async () => { deleteAllClientLogs = async () => {
const {data} = await axios.delete(`${this.URL}${ENDPOINTS.CLIENT_LOGS}`); const {data} = await http.delete(`${this.URL}${ENDPOINTS.CLIENT_LOGS}`);
return data; return data;
} }
} }

View File

@ -1,7 +1,6 @@
import axios from 'axios';
import {ENDPOINTS} from './consts'; import {ENDPOINTS} from './consts';
import adminConfigsService from '../services/AdminConfigsService'; import adminConfigsService from '../services/AdminConfigsService';
import http from './HttpAPI';
/** /**
* @interface Store * @interface Store
@ -29,7 +28,7 @@ class StorageServiceApi {
* @returns {Promise<Store[]>} - Возвращает список всех api * @returns {Promise<Store[]>} - Возвращает список всех api
*/ */
request = async () => { request = async () => {
const {data} = await axios.get(this.URL, this.OPTIONS); const {data} = await http.get(this.URL, null, this.OPTIONS);
return data; return data;
} }
@ -39,7 +38,7 @@ class StorageServiceApi {
* @returns {Promise<Store>} - Возвращает api по указанному ключу * @returns {Promise<Store>} - Возвращает api по указанному ключу
*/ */
find = async (key) => { find = async (key) => {
const {data} = await axios.get(`${this.URL}/${key}`, this.OPTIONS); const {data} = await http.get(`${this.URL}/${key}`, null, this.OPTIONS);
return data; return data;
} }
@ -49,7 +48,7 @@ class StorageServiceApi {
* @returns {Promise<Store>} - Возвращает вновь созданный элемент * @returns {Promise<Store>} - Возвращает вновь созданный элемент
*/ */
create = async (createData) => { create = async (createData) => {
const {data} = await axios.post(this.URL, createData, this.OPTIONS); const {data} = await http.post(this.URL, createData, this.OPTIONS);
return data; return data;
} }
@ -59,7 +58,7 @@ class StorageServiceApi {
* @returns {Promise<Store>} - Возвращает обновленный элемент * @returns {Promise<Store>} - Возвращает обновленный элемент
*/ */
update = async (updateData) => { update = async (updateData) => {
const {data} = await axios.put(this.URL, updateData, this.OPTIONS); const {data} = await http.put(this.URL, updateData, this.OPTIONS);
return data; return data;
} }
@ -69,7 +68,7 @@ class StorageServiceApi {
* @returns {Promise<Store>} - Возвращает удаленный элемент * @returns {Promise<Store>} - Возвращает удаленный элемент
*/ */
remove = async (key) => { remove = async (key) => {
const {data} = await axios.delete(`${this.URL}/${key}`, this.OPTIONS); const {data} = await http.delete(`${this.URL}/${key}`, null, this.OPTIONS);
return data; return data;
} }
} }

View File

@ -33,14 +33,14 @@ class TokenApi {
* Возвращает токен авторизации * Возвращает токен авторизации
*/ */
getAccessToken = () => { getAccessToken = () => {
return this.localApi.request(); return this.sessionApi.request();
} }
/** /**
* Возвращает токен ревреша авторизации * Возвращает токен ревреша авторизации
*/ */
getRefreshToken = () => { getRefreshToken = () => {
return this.sessionApi.request(); return this.localApi.request();
} }
/** /**

View File

@ -39,7 +39,7 @@ export const AUTH_SERVICE = 'http://api.auth.vigdorov.ru';
export const AUTH_ENDPOINTS = { export const AUTH_ENDPOINTS = {
AUTH: '/auth', AUTH: '/auth',
REFRESH: '/refresh', REFRESH: '/auth/refresh',
}; };
export const LOCAL_STORAGE_TYPE = { export const LOCAL_STORAGE_TYPE = {

View File

@ -5,36 +5,53 @@ import 'bootstrap';
import './services/AdminConfigsService'; import './services/AdminConfigsService';
import ApiPage from './components/api-page'; import ApiPage from './components/api-page';
import MainPage from './components/main-page'; import MainPage from './components/main-page';
import mainMenu from './components/main-menu/MainMenu'; import MainMenu from './components/main-menu/MainMenu';
import routeService from './services/RouteService'; import routeService from './services/RouteService';
import RouterPagesContainer from './components/router-pages-container/index'; import RouterPagesContainer from './components/router-pages-container/index';
import LogsPage from './components/logs-page/index'; import LogsPage from './components/logs-page/index';
import LoginPage from './components/login-page'; import LoginPage from './components/login-page';
import authServiceApi from './api/AuthServiceAPI';
mainMenu.render(); const initAppComponents = () => {
const mainMenu = new MainMenu();
mainMenu.render();
const routerPagesContainer = new RouterPagesContainer(mainMenu); const routerPagesContainer = new RouterPagesContainer(mainMenu);
/** /**
* Добавление страниц в Роутинг выполняется на странице app.js * Добавление страниц в Роутинг выполняется на странице app.js
* @example * @example
* routerPagesContainer.addRoutes([ * routerPagesContainer.addRoutes([
* {url: '/', pageComponent: MainPage}, * {url: '/', pageComponent: MainPage},
* {url: '/api', pageComponent: ApiPage}, * {url: '/api', pageComponent: ApiPage},
* ]); * ]);
*/ */
routerPagesContainer.addRoutes([ routerPagesContainer.addRoutes([
{url: '/', pageComponent: MainPage}, {url: '/', pageComponent: MainPage},
{url: '/api', pageComponent: ApiPage}, {url: '/api', pageComponent: ApiPage},
{url: '/logs', pageComponent: LogsPage}, {url: '/logs', pageComponent: LogsPage},
{url: '/login', pageComponent: LoginPage}, {url: '/login', pageComponent: LoginPage},
]); ]);
/** /**
* Этот метод генерит событие Route, чтобы все компоненты получили его после инициализации. * Этот метод генерит событие Route, чтобы все компоненты получили его после инициализации.
* Поэтому вызывать его надо в самом конце, когда уже созданы все компоненты приложения. * Поэтому вызывать его надо в самом конце, когда уже созданы все компоненты приложения.
* @example * @example
* // Вызывать его можно только один раз в программе * // Вызывать его можно только один раз в программе
* routeService.init(); * routeService.init();
*/ */
routeService.init(); routeService.init();
};
const initApp = () => {
authServiceApi.refresh()
.then(() => {
initAppComponents();
})
.catch(() => {
history.pushState({}, '', '/login');
initAppComponents();
});
};
initApp();

View File

@ -3,6 +3,7 @@ import './LoginPage.css';
import LoginForm from '../login-form'; import LoginForm from '../login-form';
import authServiceApi from '../../api/AuthServiceAPI'; import authServiceApi from '../../api/AuthServiceAPI';
import routeService from '../../services/RouteService'; import routeService from '../../services/RouteService';
import notify from '../../services/NotifyService';
class LoginPage extends Component { class LoginPage extends Component {
constructor (mainNodeSelector, parentNode) { constructor (mainNodeSelector, parentNode) {
@ -15,12 +16,12 @@ class LoginPage extends Component {
authServiceApi.auth(login, password) authServiceApi.auth(login, password)
.then(() => { .then(() => {
this.form.disabled(false); this.form.disabled(false);
notify.success('Вы авторизованы');
routeService.goTo('/'); routeService.goTo('/');
}) })
.catch((e) => { .catch((e) => {
// TODO: Времено используется alert, потом прикрутим систему нотификаций const message = e?.response?.data?.message || 'Неизвестная ошибка';
// eslint-disable-next-line no-alert notify.warn(message);
alert(e?.response?.data?.message || 'Неизвестная ошибка');
this.form.disabled(false); this.form.disabled(false);
}); });
}); });

View File

@ -82,6 +82,4 @@ class MainMenu extends Component {
} }
} }
const navMenuButtons = new MainMenu(); export default MainMenu;
export default navMenuButtons;

View File

@ -36,7 +36,7 @@ class AdminConfigsService {
* @param {'api-p' | 'api-t' | 'api-l'} apiName - api с которым хотим работать * @param {'api-p' | 'api-t' | 'api-l'} apiName - api с которым хотим работать
* @example * @example
* // Переключаем api на localhost, пишем в консоли браузера * // Переключаем api на localhost, пишем в консоли браузера
* __adminConfigs.setApi('api-l') * __adminConfig.setApi('api-l')
*/ */
setApi (apiName) { setApi (apiName) {
const options = this.getOptions(); const options = this.getOptions();
@ -53,7 +53,7 @@ class AdminConfigsService {
const adminConfigsService = new AdminConfigsService(); const adminConfigsService = new AdminConfigsService();
if (location.hostname === LOCALHOST) { if (location.hostname === LOCALHOST) {
window.__adminConfigs = adminConfigsService; window.__adminConfig = adminConfigsService;
} }
export default adminConfigsService; export default adminConfigsService;