Skip to content

Commit db1904f

Browse files
authored
Merge pull request #13 from nascob/bugfix/error-handling-login-401
Bugfix/error handling login 401
2 parents ecf257d + da15430 commit db1904f

2 files changed

Lines changed: 32 additions & 5 deletions

File tree

server/fastify-common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fastify.post<{
113113

114114
reply.send({ success: true, message: "Login successful", token });
115115
} catch (error: any) {
116-
reply.code(401).send({ error: error.message });
116+
replyError(reply, error);
117117
}
118118
});
119119

server/storytelApi.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ interface BookmarkResponse {
2121
bookmarks: Bookmark[];
2222
}
2323

24+
interface StorytelAuthError extends Error {
25+
isStorytelUnauthorized: boolean;
26+
storytelStatus?: number;
27+
storytelData?: unknown;
28+
isLoginFailure?: boolean;
29+
}
30+
2431
class StorytelClient {
2532
private client: AxiosInstance;
2633
public loginData: LoginData;
@@ -77,6 +84,7 @@ class StorytelClient {
7784
},
7885
(error) => {
7986
const url = error.config?.url || "";
87+
const isLoginRequest = url.includes("login.action");
8088
let cleanUrl = url;
8189
if (cleanUrl.includes("login.action")) {
8290
cleanUrl = cleanUrl.replace(/pwd=[^&]+/, "pwd=***");
@@ -92,8 +100,15 @@ class StorytelClient {
92100
// Propagate Storytel 401 as a distinct error type so Fastify routes
93101
// can return 401 to the frontend instead of a generic 500.
94102
if (error.response?.status === 401) {
95-
const authError: any = new Error("Storytel session expired");
103+
const authError: StorytelAuthError = new Error(
104+
isLoginRequest
105+
? "Storytel login rejected"
106+
: "Storytel session expired",
107+
) as StorytelAuthError;
96108
authError.isStorytelUnauthorized = true;
109+
authError.isLoginFailure = isLoginRequest;
110+
authError.storytelStatus = error.response.status;
111+
authError.storytelData = error.response.data;
97112
return Promise.reject(authError);
98113
}
99114
return Promise.reject(error);
@@ -109,14 +124,26 @@ class StorytelClient {
109124
}
110125

111126
async login(email: string, password: string): Promise<LoginData> {
112-
const encryptedPassword = encryptPassword(password.trim());
113-
const url = `https://www.storytel.com/api/login.action?m=1&uid=${email.trim()}&pwd=${encryptedPassword}`;
127+
const trimmedEmail = email.trim();
128+
const trimmedPassword = password.trim();
129+
const encryptedPassword = encryptPassword(trimmedPassword);
130+
const url = "https://www.storytel.com/api/login.action";
131+
const params = {
132+
m: 1,
133+
uid: trimmedEmail,
134+
pwd: encryptedPassword,
135+
};
114136

115137
try {
116-
const response = await this.client.get<LoginData>(url);
138+
const response = await this.client.get<LoginData>(url, {
139+
params,
140+
});
117141
this.loginData = response.data;
118142
return this.loginData;
119143
} catch (error: any) {
144+
if (error.isStorytelUnauthorized) {
145+
throw error;
146+
}
120147
throw new Error(`Login failed: ${error.message}`);
121148
}
122149
}

0 commit comments

Comments
 (0)