Skip to content

Commit 288566a

Browse files
committed
feat(tmdb): rework auth
1 parent ee10249 commit 288566a

22 files changed

+853
-53
lines changed

src/models/tmdb/tmdb-account.model.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export type TmdbAccountAvatar = {
2+
gravatar: {
3+
hash: string;
4+
};
5+
tmdb: {
6+
avatar_path: string;
7+
};
8+
};
9+
10+
export type TmdbAccount = {
11+
id: number;
12+
name: string;
13+
username: string;
14+
include_adult: boolean;
15+
/** The ISO 3166-1 code of the country */
16+
iso_3166_1: string;
17+
/** The ISO 639-1 code of the language */
18+
iso_639_1: string;
19+
avatar: TmdbAccountAvatar;
20+
};

src/models/tmdb/tmdb-client.model.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export type TmdbClientSettings = {
1515
endpoint: string;
1616
/** The consumer client identifier */
1717
useragent: string;
18+
/** The app api key */
19+
apiKey: string;
1820
/** The app read-only api key */
1921
readToken: string;
2022
/** token time-to-live (15 minutes) */
@@ -24,8 +26,12 @@ export type TmdbClientSettings = {
2426
export type TmdbClientAuthentication = {
2527
/** User access token if there is an active session */
2628
accessToken?: string;
27-
/** The app read-only api key */
28-
readToken?: string;
29+
/** If the session id is for a guest session */
30+
isGuest?: boolean;
31+
/** The user session id */
32+
sessionId?: string;
33+
/** The user sessionId expire date */
34+
expiresAt?: string;
2935
};
3036

3137
export type TmdbParamPagination = {
@@ -63,7 +69,9 @@ export type TmdbApiResponse<T = unknown> = ResponseOrTypedResponse<T>;
6369
export type TmdbApiQuery<T = unknown> = BaseQuery<BaseRequest, T>;
6470
export type TmdbApiTemplateOptions = BaseTemplateOptions & {
6571
/** If the method requires user authentication */
66-
auth?: boolean;
72+
auth?: 'session' | 'token' | false;
73+
/** If the method is authorized for a guest session id */
74+
guest?: boolean;
6775
/** The api version (3 or 4) */
6876
version: number | string;
6977
};

src/models/tmdb/tmdb-episode.model.ts

+5
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ export type TmdbEpisode<T extends EntityTypes = Short> = T extends Extended
4141
: T extends Short
4242
? TmdbEpisodeShort
4343
: TmdbEpisodeExtended | TmdbEpisodeShort;
44+
45+
export type TmdbEpisodeRating = TmdbEpisode & {
46+
show_id: number;
47+
rating: number;
48+
};

src/models/tmdb/tmdb-error.model.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export type TmdbError = {
2+
code: number;
3+
status: number;
4+
message: string;
5+
};
6+
7+
export const TmdbErrors = {
8+
1: { code: 1, status: 200, message: 'Success.' },
9+
2: { code: 2, status: 501, message: 'Invalid service: this service does not exist.' },
10+
3: { code: 3, status: 401, message: 'Authentication failed: You do not have permissions to access the service.' },
11+
4: { code: 4, status: 405, message: "Invalid format: This service doesn't exist in that format." },
12+
5: { code: 5, status: 422, message: 'Invalid parameters: Your request parameters are incorrect.' },
13+
6: { code: 6, status: 404, message: 'Invalid id: The pre-requisite id is invalid or not found.' },
14+
7: { code: 7, status: 401, message: 'Invalid API key: You must be granted a valid key.' },
15+
8: { code: 8, status: 403, message: 'Duplicate entry: The data you tried to submit already exists.' },
16+
9: { code: 9, status: 503, message: 'Service offline: This service is temporarily offline, try again later.' },
17+
10: { code: 10, status: 401, message: 'Suspended API key: Access to your account has been suspended, contact TMDB.' },
18+
11: { code: 11, status: 500, message: 'Internal error: Something went wrong, contact TMDB.' },
19+
12: { code: 12, status: 201, message: 'The item/record was updated successfully.' },
20+
13: { code: 13, status: 200, message: 'The item/record was deleted successfully.' },
21+
14: { code: 14, status: 401, message: 'Authentication failed.' },
22+
15: { code: 15, status: 500, message: 'Failed.' },
23+
16: { code: 16, status: 401, message: 'Device denied.' },
24+
17: { code: 17, status: 401, message: 'Session denied.' },
25+
18: { code: 18, status: 400, message: 'Validation failed.' },
26+
19: { code: 19, status: 406, message: 'Invalid accept header.' },
27+
20: { code: 20, status: 422, message: 'Invalid date range: Should be a range no longer than 14 days.' },
28+
21: { code: 21, status: 200, message: 'Entry not found: The item you are trying to edit cannot be found.' },
29+
22: { code: 22, status: 400, message: 'Invalid page: Pages start at 1 and max at 500. They are expected to be an integer.' },
30+
23: { code: 23, status: 400, message: 'Invalid date: Format needs to be YYYY-MM-DD.' },
31+
24: { code: 24, status: 504, message: 'Your request to the backend server timed out. Try again.' },
32+
25: { code: 25, status: 429, message: 'Your request count (#) is over the allowed limit of (40).' },
33+
26: { code: 26, status: 400, message: 'You must provide a username and password.' },
34+
27: { code: 27, status: 400, message: 'Too many append to response objects: The maximum number of remote calls is 20.' },
35+
28: { code: 28, status: 400, message: 'Invalid timezone: Please consult the documentation for a valid timezone.' },
36+
29: { code: 29, status: 400, message: 'You must confirm this action: Please provide a confirm=true parameter.' },
37+
30: { code: 30, status: 401, message: 'Invalid username and/or password: You did not provide a valid login.' },
38+
31: { code: 31, status: 401, message: 'Account disabled: Your account is no longer active. Contact TMDB if this is an error.' },
39+
32: { code: 32, status: 401, message: 'Email not verified: Your email address has not been verified.' },
40+
33: { code: 33, status: 401, message: 'Invalid request token: The request token is either expired or invalid.' },
41+
34: { code: 34, status: 404, message: 'The resource you requested could not be found.' },
42+
35: { code: 35, status: 401, message: 'Invalid token.' },
43+
36: { code: 36, status: 401, message: "This token hasn't been granted write permission by the user." },
44+
37: { code: 37, status: 404, message: 'The requested session could not be found.' },
45+
38: { code: 38, status: 401, message: "You don't have permission to edit this resource." },
46+
39: { code: 39, status: 401, message: 'This resource is private.' },
47+
40: { code: 40, status: 200, message: 'Nothing to update.' },
48+
41: { code: 41, status: 422, message: "This request token hasn't been approved by the user." },
49+
42: { code: 42, status: 405, message: 'This request method is not supported for this resource.' },
50+
43: { code: 43, status: 502, message: "Couldn't connect to the backend server." },
51+
44: { code: 44, status: 500, message: 'The ID is invalid.' },
52+
45: { code: 45, status: 403, message: 'This user has been suspended.' },
53+
46: { code: 46, status: 503, message: 'The API is undergoing maintenance. Try again later.' },
54+
47: { code: 47, status: 400, message: 'The input is not valid.' },
55+
};

src/models/tmdb/tmdb-list.model.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,16 @@ export type TmdbListV4 = BaseTmdbList & {
3535
item_count: number;
3636
object_ids: Record<string, string>;
3737
sort_by: string;
38+
};
3839

39-
// page: number;
40-
// results: TmdbMovieShort[];
41-
// total_pages: number;
42-
// total_results: number;
40+
export type TmdbListV3 = {
41+
id: number;
42+
item_count: number;
43+
description: string;
44+
favorite_count: number;
45+
/** The ISO 639-1 code of the language */
46+
iso_639_1: string;
47+
list_type: 'movie' | 'tv';
48+
name: string;
49+
poster_path: string;
4350
};

src/services/common/base-client.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ describe('base-client.ts', () => {
484484
expect(result).toBe('{"requiredBody":"requiredBody"}');
485485
});
486486

487-
it('should parse body to JSON string', () => {
487+
it('should throw an error for missing mandatory body parameter', () => {
488488
expect.assertions(1);
489489

490490
const mockBody: Record<string, unknown> = { ...mockParams, optionalBody: 'optionalBody' };

src/services/common/base-client.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ export const parseBody = <T extends RecursiveRecord = RecursiveRecord>(template:
414414
});
415415

416416
Object.keys(template).forEach(key => {
417-
if (template[key] === true && !(key in _body)) throw new Error(`Missing mandatory body parameter: '${key}'`);
417+
if (template[key] === true && [undefined, null, ''].includes(params[key])) throw new Error(`Missing mandatory body parameter: '${key}'`);
418418
});
419419

420420
return JSON.stringify(_body);
@@ -471,7 +471,7 @@ export const parseUrl = <P extends RecursiveRecord = RecursiveRecord, O extends
471471
const _value = params[key] ?? value;
472472

473473
// If a value is found we encode
474-
if (_value !== undefined && _value !== '') {
474+
if (![undefined, null, ''].includes(_value)) {
475475
url.searchParams.set(key, typeof _value === 'object' ? JSON.stringify(_value) : _value);
476476
}
477477
// If the parameter is required we raise error

0 commit comments

Comments
 (0)