1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 12:56:41 +07:00

login mechanism

This commit is contained in:
muerwre 2019-04-04 16:36:50 +07:00
parent 6168841f78
commit 9528e7f699
27 changed files with 528 additions and 96 deletions

View file

@ -1,3 +1,16 @@
import { USER_ACTIONS } from "$redux/user/constants";
import { IUserProfile } from "$redux/user/reducer";
export const someAction = () => ({ type: USER_ACTIONS.SOME_ACTION });
export const userSendLoginRequest = ({
username, password
}: {
username: string, password: string
}) => ({ type: USER_ACTIONS.SEND_LOGIN_REQUEST, username, password });
export const userSetLoginError = ({
error
}: {
error: string
}) => ({ type: USER_ACTIONS.SET_LOGIN_ERROR, error });
export const userSetUser = (profile: Partial<IUserProfile>) => ({ type: USER_ACTIONS.SET_USER, profile });

12
src/redux/user/api.ts Normal file
View file

@ -0,0 +1,12 @@
import { api } from "$utils/api";
import { API } from "$constants/api";
import { IApiUser } from "$redux/user/constants";
export const apiUserLogin = (
{ username, password }:
{ username: string, password: string }
): Promise<{ token: string, status?: number, user?: IApiUser }> => (
api.post(API.USER.LOGIN, { username, password })
.then(r => r && r.data && { token: r.data.token, user: r.data.user, status: 200 })
.catch( (r) => ({ token: '', user: null, status: parseInt(r.response.status) }))
);

View file

@ -1,3 +1,24 @@
export const USER_ACTIONS = {
SOME_ACTION: 'SOME_ACTION',
SEND_LOGIN_REQUEST: 'SEND_LOGIN_REQUEST',
SET_LOGIN_ERROR: 'SET_LOGIN_ERROR',
SET_USER: 'SET_USER',
};
export const USER_ERRORS = {
INVALID_CREDENTIALS: 'Неверное имя пользователя или пароль. Очень жаль.',
EMPTY_CREDENTIALS: 'Давайте введем логин и пароль. Это обязательно.'
};
export const USER_STATUSES = {
404: USER_ERRORS.INVALID_CREDENTIALS,
};
export interface IApiUser {
id: number,
username: string,
email: string,
role: string,
activated: boolean,
createdAt: string,
updatedAt: string,
}

View file

@ -1,5 +1,5 @@
import { createReducer } from 'reduxsauce';
import * as ACTIONS from "$redux/user/actions";
import * as ActionCreators from "$redux/user/actions";
import { USER_ACTIONS } from "$redux/user/constants";
export interface IUserProfile {
@ -8,13 +8,14 @@ export interface IUserProfile {
email: string,
role: string,
activated: boolean,
token: string,
}
export interface IUserFormStateLogin {
error: string,
}
export type IRootState = Readonly<{
export type IUserState = Readonly<{
profile: IUserProfile,
form_state: {
login: IUserFormStateLogin,
@ -23,23 +24,40 @@ export type IRootState = Readonly<{
type UnsafeReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
interface ActionHandler<T> {
(state: IRootState, payload: UnsafeReturnType<T>): IRootState;
(state: IUserState, payload: UnsafeReturnType<T>): IUserState;
}
const someActionHandler: ActionHandler<typeof ACTIONS.someAction> = (state) => {
return { ...state };
};
const setLoginErrorHandler: ActionHandler<typeof ActionCreators.userSetLoginError> = (state, { error }) => ({
...state,
form_state: {
...state.form_state,
login: {
...state.form_state.login,
error,
}
}
});
const setUserHandler: ActionHandler<typeof ActionCreators.userSetUser> = (state, { profile }) => ({
...state,
profile: {
...state.profile,
...profile,
}
});
const HANDLERS = {
[USER_ACTIONS.SOME_ACTION]: someActionHandler,
[USER_ACTIONS.SET_LOGIN_ERROR]: setLoginErrorHandler,
[USER_ACTIONS.SET_USER]: setUserHandler,
};
const INITIAL_STATE: IRootState = {
const INITIAL_STATE: IUserState = {
profile: {
id: 0,
username: '',
email: '',
role: '',
token: '',
activated: false,
},
form_state: {

View file

@ -1,25 +1,34 @@
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
import { delay } from 'redux-saga';
import { USER_ACTIONS } from "$redux/user/constants";
import { call, put, takeLatest } from 'redux-saga/effects';
import { SagaIterator } from 'redux-saga';
import { IApiUser, USER_ACTIONS, USER_ERRORS, USER_STATUSES } from "$redux/user/constants";
import * as ActionCreators from '$redux/user/actions';
import { apiUserLogin } from "$redux/user/api";
import { userSetLoginError, userSetUser } from "$redux/user/actions";
import { push } from 'connected-react-router'
// Worker Saga for SET_EDITOR_LOCATION_INPUT reducer
/*
function* fetchSuggestions({ payload }) {
const { value } = payload;
function* sendLoginRequestSaga({ username, password }: ReturnType<typeof ActionCreators.userSendLoginRequest>): SagaIterator {
if (!username || !password) return yield put(userSetLoginError({ error: USER_ERRORS.EMPTY_CREDENTIALS }));
yield delay(300);
try {
const results = yield call(someFunction, arguments);
yield put({ type: TYPES.ANOTHER_ACTION, payload: { results } });
} catch (e) {
yield put({ type: TYPES.ANOTHER_ACTION, payload: { results } });
}
const { token, status, user }: { token: string, status: number, user: IApiUser } = yield call(apiUserLogin, { username, password });
if (!token) return yield put(userSetLoginError({ error: USER_STATUSES[status] || USER_ERRORS.INVALID_CREDENTIALS }));
const { id, role, email, activated } = user;
yield put(userSetUser({
token,
id,
role,
email,
username: user.username,
activated,
}));
yield put(push('/'));
}
*/
function* mySaga() {
// fetch autocompletion on location input
//yield takeLatest(TYPES.ACTION, function);
yield takeLatest(USER_ACTIONS.SEND_LOGIN_REQUEST, sendLoginRequestSaga);
}
export default mySaga;