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:
parent
956802d5a5
commit
dc6f72baf1
26 changed files with 269 additions and 374 deletions
18
src/redux/auth/actions.ts
Normal file
18
src/redux/auth/actions.ts
Normal 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
15
src/redux/auth/api.ts
Normal 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)
|
||||
);
|
49
src/redux/auth/constants.ts
Normal file
49
src/redux/auth/constants.ts
Normal 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,
|
||||
}
|
36
src/redux/auth/handlers.ts
Normal file
36
src/redux/auth/handlers.ts
Normal 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
19
src/redux/auth/reducer.ts
Normal 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
33
src/redux/auth/sagas.ts
Normal 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;
|
4
src/redux/auth/selectors.ts
Normal file
4
src/redux/auth/selectors.ts
Normal 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;
|
14
src/redux/auth/transforms.ts
Normal file
14
src/redux/auth/transforms.ts
Normal 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
26
src/redux/auth/types.ts
Normal 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;
|
||||
};
|
||||
}>;
|
Loading…
Add table
Add a link
Reference in a new issue