1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 21:06:42 +07:00

getting token / error

This commit is contained in:
muerwre 2019-08-03 12:12:23 +07:00
parent 956802d5a5
commit dc6f72baf1
26 changed files with 269 additions and 374 deletions

18
src/redux/auth/actions.ts Normal file
View file

@ -0,0 +1,18 @@
import { AUTH_USER_ACTIONS } from "~/redux/auth/constants";
import {IAuthState, IUser} from "~/redux/auth/types";
export const userSendLoginRequest = ({
username, password
}: {
username: string, password: string
}) => ({ type: AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, username, password });
export const userSetLoginError = (error: IAuthState['login']['error']) => ({
type: AUTH_USER_ACTIONS.SET_LOGIN_ERROR, error
});
export const authSetToken = (token: IAuthState['token']) => ({
type: AUTH_USER_ACTIONS.SET_TOKEN, token,
});
export const authSetUser = (profile: Partial<IUser>) => ({ type: AUTH_USER_ACTIONS.SET_USER, profile });

15
src/redux/auth/api.ts Normal file
View file

@ -0,0 +1,15 @@
import {api, authMiddleware, errorMiddleware, resultMiddleware} from "~/utils/api";
import { API } from "~/constants/api";
import { IApiUser } from "~/redux/auth/constants";
import {IResultWithStatus} from "~/redux/types";
import {userLoginTransform} from "~/redux/auth/transforms";
export const apiUserLogin = (
{ username, password }:
{ username: string, password: string }
): Promise<IResultWithStatus<{ token: string, status?: number, user?: IApiUser }>> => (
api.post(API.USER.LOGIN, { username, password })
.then(resultMiddleware)
.catch(errorMiddleware)
.then(userLoginTransform)
);

View file

@ -0,0 +1,49 @@
import {IToken, IUser} from "~/redux/auth/types";
export const AUTH_USER_ACTIONS = {
SEND_LOGIN_REQUEST: 'SEND_LOGIN_REQUEST',
SET_LOGIN_ERROR: 'SET_LOGIN_ERROR',
SET_USER: 'SET_USER',
SET_TOKEN: 'SET_TOKEN',
};
export const USER_ERRORS = {
INVALID_CREDENTIALS: 'Неверное имя пользователя или пароль. Очень жаль.',
EMPTY_CREDENTIALS: 'Давайте введем логин и пароль. Это обязательно.'
};
export const USER_STATUSES = {
404: USER_ERRORS.INVALID_CREDENTIALS,
};
export const USER_ROLES = {
GUEST: 'guest',
USER: 'user',
ADMIN: 'admin',
};
export const EMPTY_TOKEN: IToken = {
access: null,
refresh: null,
};
export const EMPTY_USER: IUser = {
id: null,
role: USER_ROLES.GUEST,
email: null,
name: null,
username: null,
photo: null,
is_activated: false,
is_user: false,
};
export interface IApiUser {
id: number,
username: string,
email: string,
role: string,
activated: boolean,
createdAt: string,
updatedAt: string,
}

View file

@ -0,0 +1,36 @@
import {AUTH_USER_ACTIONS} from "~/redux/auth/constants";
import * as ActionCreators from "~/redux/auth/actions";
import {IAuthState} from "~/redux/auth/types";
interface ActionHandler<T> {
(state: IAuthState, payload: T extends (...args: any[]) => infer R ? R : any): IAuthState;
}
const setLoginError: ActionHandler<typeof ActionCreators.userSetLoginError> = (
state,
{ error }
) => ({
...state,
login: {
...state.login,
error,
}
});
const setUser: ActionHandler<typeof ActionCreators.authSetUser> = (state, { profile }) => ({
...state,
user: {
...state.user,
...profile
}
});
const setToken: ActionHandler<typeof ActionCreators.authSetToken> = (state, { token }) => ({
...state, token,
});
export const AUTH_USER_HANDLERS = {
[AUTH_USER_ACTIONS.SET_LOGIN_ERROR]: setLoginError,
[AUTH_USER_ACTIONS.SET_USER]: setUser,
[AUTH_USER_ACTIONS.SET_TOKEN]: setToken,
};

19
src/redux/auth/reducer.ts Normal file
View file

@ -0,0 +1,19 @@
import {EMPTY_TOKEN, EMPTY_USER, AUTH_USER_ACTIONS} from "~/redux/auth/constants";
import { createReducer } from "~/utils/reducer";
import {IAuthState} from "~/redux/auth/types";
import {AUTH_USER_HANDLERS} from "~/redux/auth/handlers";
const HANDLERS = {
...AUTH_USER_HANDLERS,
};
const INITIAL_STATE: IAuthState = {
token: { ...EMPTY_TOKEN },
user: { ...EMPTY_USER },
login: {
error: null,
is_loading: false,
},
};
export default createReducer(INITIAL_STATE, HANDLERS);

33
src/redux/auth/sagas.ts Normal file
View file

@ -0,0 +1,33 @@
import {call, put, takeLatest } from 'redux-saga/effects';
import { SagaIterator } from 'redux-saga';
import {AUTH_USER_ACTIONS} from "~/redux/auth/constants";
import * as ActionCreators from '~/redux/auth/actions';
import {authSetToken, userSetLoginError} from "~/redux/auth/actions";
import {apiUserLogin} from "~/redux/auth/api";
function* sendLoginRequestSaga({ username, password }: ReturnType<typeof ActionCreators.userSendLoginRequest>): SagaIterator {
if (!username || !password) return;
const { error, data: { access, refresh, user }} = yield call(apiUserLogin, { username, password });
console.log({ access, refresh, user, error });
if (error) return yield put(userSetLoginError(error));
yield put(authSetToken({ access, refresh }));
// 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: is_activated } = user;
//
// yield put(userSetUser({ token, id, role, email, username: user.username, is_activated, is_user: true }));
// yield put(push('/'));
}
function* mySaga() {
yield takeLatest(AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, sendLoginRequestSaga);
}
export default mySaga;

View file

@ -0,0 +1,4 @@
import {IState} from "~/redux/store";
export const selectUser = (state: IState): IState['auth']['user'] => state.auth.user;
export const selectAuthLogin = (state: IState): IState['auth']['login'] => state.auth.login;

View file

@ -0,0 +1,14 @@
import {IResultWithStatus} from "~/redux/types";
export const userLoginTransform = ({ status, data,error }: IResultWithStatus<any>): IResultWithStatus<any> => {
switch(true) {
case status === 401 || !data.access || data.refresh:
return { status, data, error: 'Пользователь не найден' };
case status === 200:
return { status, data, error: null };
default:
return { status, data, error: error || 'Неизвестная ошибка' };
}
}

26
src/redux/auth/types.ts Normal file
View file

@ -0,0 +1,26 @@
export interface IToken {
access: string;
refresh: string;
}
export interface IUser {
id: number;
username: string;
email: string;
role: string;
photo: string;
name: string;
is_activated: boolean;
is_user: boolean;
}
export type IAuthState = Readonly<{
user: IUser;
token: IToken;
login: {
error: string;
is_loading: boolean;
};
}>;