mirror of
https://github.com/usatiuk/photos.git
synced 2025-10-28 15:27:49 +01:00
fix failed login hanging bug
This commit is contained in:
@@ -15,7 +15,7 @@ import { config, EnvType } from "~config";
|
|||||||
import { userRouter } from "~routes/users";
|
import { userRouter } from "~routes/users";
|
||||||
import { devRouter } from "~routes/dev";
|
import { devRouter } from "~routes/dev";
|
||||||
import { photosRouter } from "~routes/photos";
|
import { photosRouter } from "~routes/photos";
|
||||||
import { TUserJWT } from "~shared/types";
|
import { TAPIErrorResponse, TUserJWT } from "~shared/types";
|
||||||
|
|
||||||
export interface IAppState extends Koa.DefaultState {
|
export interface IAppState extends Koa.DefaultState {
|
||||||
user?: TUserJWT;
|
user?: TUserJWT;
|
||||||
@@ -101,6 +101,6 @@ app.on("error", (err, ctx) => {
|
|||||||
console.log(err);
|
console.log(err);
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
error: err.message,
|
error: err.message,
|
||||||
data: false,
|
data: null,
|
||||||
};
|
} as TAPIErrorResponse;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ describe("users", function () {
|
|||||||
|
|
||||||
const body = response.body as TUserLoginRespBody;
|
const body = response.body as TUserLoginRespBody;
|
||||||
expect(body.error).to.be.equal("User not found");
|
expect(body.error).to.be.equal("User not found");
|
||||||
expect(body.data).to.be.false;
|
expect(body.data).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should signup user", async function () {
|
it("should signup user", async function () {
|
||||||
@@ -127,7 +127,7 @@ describe("users", function () {
|
|||||||
const body = response.body as TUserSignupRespBody;
|
const body = response.body as TUserSignupRespBody;
|
||||||
|
|
||||||
expect(body.error).to.be.equal("Signups not allowed");
|
expect(body.error).to.be.equal("Signups not allowed");
|
||||||
expect(body.data).to.be.false;
|
expect(body.data).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should signup first user and it should be admin, do not signup new users (by default)", async function () {
|
it("should signup first user and it should be admin, do not signup new users (by default)", async function () {
|
||||||
@@ -170,7 +170,7 @@ describe("users", function () {
|
|||||||
const body2 = response2.body as TUserSignupRespBody;
|
const body2 = response2.body as TUserSignupRespBody;
|
||||||
|
|
||||||
expect(body2.error).to.be.equal("Signups not allowed");
|
expect(body2.error).to.be.equal("Signups not allowed");
|
||||||
expect(body2.data).to.be.false;
|
expect(body2.data).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should signup first user and it should be admin, but not new ones", async function () {
|
it("should signup first user and it should be admin, but not new ones", async function () {
|
||||||
@@ -240,7 +240,7 @@ describe("users", function () {
|
|||||||
const body = response.body as TUserSignupRespBody;
|
const body = response.body as TUserSignupRespBody;
|
||||||
|
|
||||||
expect(body.error).to.be.equal("User already exists");
|
expect(body.error).to.be.equal("User already exists");
|
||||||
expect(body.data).to.be.false;
|
expect(body.data).to.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should change user's password", async function () {
|
it("should change user's password", async function () {
|
||||||
@@ -291,6 +291,6 @@ describe("users", function () {
|
|||||||
const badLoginBody = badLoginResponse.body as TUserLoginRespBody;
|
const badLoginBody = badLoginResponse.body as TUserLoginRespBody;
|
||||||
|
|
||||||
expect(badLoginBody.error).to.be.equal("User not found");
|
expect(badLoginBody.error).to.be.equal("User not found");
|
||||||
expect(badLoginBody.data).to.be.false;
|
expect(badLoginBody.data).to.be.null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
73
frontend/package-lock.json
generated
73
frontend/package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"@parcel/config-default": "^2.9.3",
|
"@parcel/config-default": "^2.9.3",
|
||||||
"@parcel/transformer-sass": "^2.9.3",
|
"@parcel/transformer-sass": "^2.9.3",
|
||||||
"@parcel/transformer-typescript-tsc": "^2.9.3",
|
"@parcel/transformer-typescript-tsc": "^2.9.3",
|
||||||
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||||
"@typescript-eslint/parser": "^6.2.0",
|
"@typescript-eslint/parser": "^6.2.0",
|
||||||
"@wojtekmaj/enzyme-adapter-react-17": "^0",
|
"@wojtekmaj/enzyme-adapter-react-17": "^0",
|
||||||
@@ -2989,6 +2990,29 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz",
|
||||||
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@reduxjs/toolkit": {
|
||||||
|
"version": "1.9.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
|
||||||
|
"integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"immer": "^9.0.21",
|
||||||
|
"redux": "^4.2.1",
|
||||||
|
"redux-thunk": "^2.4.2",
|
||||||
|
"reselect": "^4.1.8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.9.0 || ^17.0.0 || ^18",
|
||||||
|
"react-redux": "^7.2.1 || ^8.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.27.8",
|
"version": "0.27.8",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||||
@@ -6874,6 +6898,15 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immer": {
|
||||||
|
"version": "9.0.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
|
||||||
|
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/immer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/immutable": {
|
"node_modules/immutable": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
||||||
@@ -10097,6 +10130,14 @@
|
|||||||
"@redux-saga/core": "^1.2.3"
|
"@redux-saga/core": "^1.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redux-thunk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"redux": "^4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.13.11",
|
"version": "0.13.11",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||||
@@ -10136,6 +10177,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/reselect": {
|
||||||
|
"version": "4.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||||
|
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.3",
|
"version": "1.22.3",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
|
||||||
@@ -13385,6 +13431,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz",
|
||||||
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
||||||
},
|
},
|
||||||
|
"@reduxjs/toolkit": {
|
||||||
|
"version": "1.9.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz",
|
||||||
|
"integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==",
|
||||||
|
"requires": {
|
||||||
|
"immer": "^9.0.21",
|
||||||
|
"redux": "^4.2.1",
|
||||||
|
"redux-thunk": "^2.4.2",
|
||||||
|
"reselect": "^4.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@sinclair/typebox": {
|
"@sinclair/typebox": {
|
||||||
"version": "0.27.8",
|
"version": "0.27.8",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||||
@@ -16126,6 +16183,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ=="
|
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ=="
|
||||||
},
|
},
|
||||||
|
"immer": {
|
||||||
|
"version": "9.0.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
|
||||||
|
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
|
||||||
|
},
|
||||||
"immutable": {
|
"immutable": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
|
||||||
@@ -18387,6 +18449,12 @@
|
|||||||
"@redux-saga/core": "^1.2.3"
|
"@redux-saga/core": "^1.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redux-thunk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.13.11",
|
"version": "0.13.11",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||||
@@ -18417,6 +18485,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
},
|
},
|
||||||
|
"reselect": {
|
||||||
|
"version": "4.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||||
|
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.22.3",
|
"version": "1.22.3",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"@parcel/config-default": "^2.9.3",
|
"@parcel/config-default": "^2.9.3",
|
||||||
"@parcel/transformer-sass": "^2.9.3",
|
"@parcel/transformer-sass": "^2.9.3",
|
||||||
"@parcel/transformer-typescript-tsc": "^2.9.3",
|
"@parcel/transformer-typescript-tsc": "^2.9.3",
|
||||||
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||||
"@typescript-eslint/parser": "^6.2.0",
|
"@typescript-eslint/parser": "^6.2.0",
|
||||||
"@wojtekmaj/enzyme-adapter-react-17": "^0",
|
"@wojtekmaj/enzyme-adapter-react-17": "^0",
|
||||||
|
|||||||
@@ -26,9 +26,8 @@ function* startSpinner() {
|
|||||||
|
|
||||||
function* authStart(action: IAuthStartAction) {
|
function* authStart(action: IAuthStartAction) {
|
||||||
const { username, password } = action.payload;
|
const { username, password } = action.payload;
|
||||||
|
const spinner = yield fork(startSpinner);
|
||||||
try {
|
try {
|
||||||
const spinner = yield fork(startSpinner);
|
|
||||||
|
|
||||||
const { response, timeout } = yield race({
|
const { response, timeout } = yield race({
|
||||||
response: call(login, username, password),
|
response: call(login, username, password),
|
||||||
timeout: delay(10000),
|
timeout: delay(10000),
|
||||||
@@ -47,15 +46,15 @@ function* authStart(action: IAuthStartAction) {
|
|||||||
yield put(authFail(response.error));
|
yield put(authFail(response.error));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
yield cancel(spinner);
|
||||||
yield put(authFail("Internal error"));
|
yield put(authFail("Internal error"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* signupStart(action: ISignupStartAction) {
|
function* signupStart(action: ISignupStartAction) {
|
||||||
const { username, password, email } = action.payload;
|
const { username, password, email } = action.payload;
|
||||||
|
const spinner = yield fork(startSpinner);
|
||||||
try {
|
try {
|
||||||
const spinner = yield fork(startSpinner);
|
|
||||||
|
|
||||||
const { response, timeout } = yield race({
|
const { response, timeout } = yield race({
|
||||||
response: call(signup, username, password, email),
|
response: call(signup, username, password, email),
|
||||||
timeout: delay(10000),
|
timeout: delay(10000),
|
||||||
@@ -74,6 +73,7 @@ function* signupStart(action: ISignupStartAction) {
|
|||||||
yield put(authFail(response.error));
|
yield put(authFail(response.error));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
yield cancel(spinner);
|
||||||
yield put(authFail(e.toString()));
|
yield put(authFail(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { applyMiddleware, createStore } from "redux";
|
|
||||||
import { composeWithDevTools } from "redux-devtools-extension";
|
import { composeWithDevTools } from "redux-devtools-extension";
|
||||||
import { persistStore } from "redux-persist";
|
import { persistStore } from "redux-persist";
|
||||||
import createSagaMiddlware from "redux-saga";
|
import createSagaMiddlware from "redux-saga";
|
||||||
import { rootReducer } from "../redux/reducers";
|
import { configureStore } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
import { setToken } from "./api/utils";
|
import { setToken } from "./api/utils";
|
||||||
import { authSaga } from "./auth/sagas";
|
import { authSaga } from "./auth/sagas";
|
||||||
import { photosSaga } from "./photos/sagas";
|
import { photosSaga } from "./photos/sagas";
|
||||||
import { getUser } from "./user/actions";
|
import { getUser } from "./user/actions";
|
||||||
import { userSaga } from "./user/sagas";
|
import { userSaga } from "./user/sagas";
|
||||||
|
import { rootReducer } from "../redux/reducers";
|
||||||
|
|
||||||
const sagaMiddleware = createSagaMiddlware();
|
const sagaMiddleware = createSagaMiddlware();
|
||||||
|
|
||||||
export const store = createStore(
|
export const store = configureStore({
|
||||||
rootReducer,
|
reducer: rootReducer,
|
||||||
composeWithDevTools(applyMiddleware(sagaMiddleware)),
|
middleware: [sagaMiddleware],
|
||||||
);
|
});
|
||||||
|
|
||||||
export const persistor = persistStore(store, null, () => {
|
export const persistor = persistStore(store, null, () => {
|
||||||
const state = store.getState();
|
const state = store.getState();
|
||||||
|
|||||||
Reference in New Issue
Block a user