forked from trycourier/courier-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[C-6392] Add support for token management (trycourier#100)
* WIP * Rename users folder * Add tests for tokenManagement * Update changelog
- Loading branch information
Showing
7 changed files
with
249 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import axios from "axios"; | ||
import MockAdapter from "axios-mock-adapter"; | ||
import { CourierClient } from ".."; | ||
import { UserToken } from "../token-management/types"; | ||
|
||
const mock = new MockAdapter(axios); | ||
const mockToken: UserToken = { | ||
token: "abc", | ||
provider_key: "apn", | ||
}; | ||
|
||
describe("CourierAudiences", () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
mock.reset(); | ||
}); | ||
|
||
const { tokenManagement } = CourierClient({ | ||
authorizationToken: "AUTH_TOKEN", | ||
}); | ||
|
||
describe("putUserTokens", () => { | ||
it("resolves void when the put call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onPut("/users/me/tokens").reply(204); | ||
const prom = tokenManagement.putUserTokens({ | ||
user_id: "me", | ||
tokens: [mockToken], | ||
}); | ||
await expect(prom).resolves.not.toThrow(); | ||
}); | ||
}); | ||
|
||
describe("putUserToken", () => { | ||
it("resolves void when the put call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onPut("/users/me/tokens/abc").reply(204); | ||
const prom = tokenManagement.putUserToken({ | ||
user_id: "me", | ||
token: mockToken, | ||
}); | ||
await expect(prom).resolves.not.toThrow(); | ||
}); | ||
}); | ||
|
||
describe("patchUserToken", () => { | ||
it("resolves void when the put call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onPatch("/users/me/tokens/abc").reply(204); | ||
const prom = tokenManagement.patchUserToken({ | ||
user_id: "me", | ||
token: "abc", | ||
patch: [{ op: "replace", path: "status", value: "revoked" }], | ||
}); | ||
await expect(prom).resolves.not.toThrow(); | ||
}); | ||
}); | ||
|
||
describe("getUserToken", () => { | ||
it("resolves with the token when the get call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onGet("/users/me/tokens/abc").reply(200, mockToken); | ||
const result = await tokenManagement.getUserToken({ | ||
user_id: "me", | ||
token: "abc", | ||
}); | ||
expect(result).toMatchObject(mockToken); | ||
}); | ||
}); | ||
|
||
describe("getUserTokens", () => { | ||
it("resolves with the tokens when the get call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onGet("/users/me/tokens").reply(200, { tokens: [mockToken] }); | ||
const result = await tokenManagement.getUserTokens({ | ||
user_id: "me", | ||
}); | ||
expect(result).toMatchObject({ tokens: [mockToken] }); | ||
}); | ||
}); | ||
|
||
describe("deleteUserToken", () => { | ||
it("resolves with the token when the delete call succeeds", async () => { | ||
expect.assertions(1); | ||
|
||
mock.onDelete("/users/me/tokens/abc").reply(204); | ||
const prom = tokenManagement.deleteUserToken({ | ||
user_id: "me", | ||
token: "abc", | ||
}); | ||
await expect(prom).resolves.not.toThrow(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { ICourierClientConfiguration } from "../types"; | ||
import { | ||
DeleteUserTokenOpts, | ||
GetUserTokenOpts, | ||
GetUserTokenResponse, | ||
GetUserTokensOpts, | ||
PatchUserTokenOpts, | ||
PutUserTokenOpts, | ||
PutUserTokensOpts, | ||
} from "./types"; | ||
|
||
/** Associate a group of tokens with the supplied :user_id. Will overwrite any existing tokens associated with that user. */ | ||
const putUserTokens = (options: ICourierClientConfiguration) => { | ||
return async (opts: PutUserTokensOpts): Promise<void> => { | ||
await options.httpClient.put(`/users/${opts.user_id}/tokens`, { | ||
tokens: opts.tokens, | ||
}); | ||
}; | ||
}; | ||
|
||
/** Associate a token with the supplied :user_id. If token exists it's value will be replaced with the passed body, otherwise the token will be created. */ | ||
const putUserToken = (options: ICourierClientConfiguration) => { | ||
return async (opts: PutUserTokenOpts): Promise<void> => { | ||
await options.httpClient.put( | ||
`/users/${opts.user_id}/tokens/${opts.token.token}`, | ||
opts.token | ||
); | ||
}; | ||
}; | ||
|
||
const patchUserToken = (options: ICourierClientConfiguration) => { | ||
return async (opts: PatchUserTokenOpts): Promise<void> => { | ||
await options.httpClient.patch( | ||
`/users/${opts.user_id}/tokens/${opts.token}`, | ||
{ patch: opts.patch } | ||
); | ||
}; | ||
}; | ||
|
||
const getUserToken = (options: ICourierClientConfiguration) => { | ||
return async (opts: GetUserTokenOpts): Promise<GetUserTokenResponse> => { | ||
const res = await options.httpClient.get( | ||
`/users/${opts.user_id}/tokens/${opts.token}` | ||
); | ||
return res.data as GetUserTokenResponse; | ||
}; | ||
}; | ||
|
||
const getUserTokens = (options: ICourierClientConfiguration) => { | ||
return async ( | ||
opts: GetUserTokensOpts | ||
): Promise<{ tokens: GetUserTokenResponse[] }> => { | ||
const res = await options.httpClient.get(`/users/${opts.user_id}/tokens`); | ||
return res.data as { tokens: GetUserTokenResponse[] }; | ||
}; | ||
}; | ||
|
||
const deleteUserToken = (options: ICourierClientConfiguration) => { | ||
return async (opts: DeleteUserTokenOpts): Promise<void> => { | ||
await options.httpClient.delete( | ||
`/users/${opts.user_id}/tokens/${opts.token}` | ||
); | ||
}; | ||
}; | ||
|
||
export const tokenManagement = (options: ICourierClientConfiguration) => { | ||
return { | ||
putUserTokens: putUserTokens(options), | ||
putUserToken: putUserToken(options), | ||
patchUserToken: patchUserToken(options), | ||
getUserToken: getUserToken(options), | ||
getUserTokens: getUserTokens(options), | ||
deleteUserToken: deleteUserToken(options), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
export interface UserToken { | ||
token: string; | ||
|
||
provider_key: "firebase-fcm" | "apn" | "expo" | "onesignal"; | ||
|
||
/** ISO 8601 Date. Set to false to disable expiration */ | ||
expiry_date?: string | false; | ||
|
||
/** Additional properties to be passed to provider or to be generically associated with the token */ | ||
properties?: { [key: string]: any }; | ||
|
||
device?: { | ||
app_id?: string; | ||
ad_id?: string; | ||
device_id?: string; | ||
platform?: string; | ||
manufacturer?: string; | ||
model?: string; | ||
}; | ||
|
||
tracking?: { | ||
os_version?: string; | ||
ip?: string; | ||
lat?: string; | ||
long?: string; | ||
}; | ||
} | ||
|
||
export interface GetUserTokenResponse extends UserToken { | ||
status: "active" | "unknown" | "failed" | "revoked"; | ||
status_reason?: string; | ||
} | ||
|
||
export interface PutUserTokensOpts { | ||
user_id: string; | ||
tokens: UserToken[]; | ||
} | ||
|
||
export interface PutUserTokenOpts { | ||
user_id: string; | ||
token: UserToken; | ||
} | ||
|
||
export interface PatchUserTokenOpts { | ||
user_id: string; | ||
token: string; | ||
patch: { | ||
op: "replace" | "add" | "remove" | "copy" | "move" | "test"; | ||
path: string; | ||
value?: string; | ||
}[]; | ||
} | ||
|
||
export interface GetUserTokenOpts { | ||
user_id: string; | ||
token: string; | ||
} | ||
|
||
export interface GetUserTokensOpts { | ||
user_id: string; | ||
} | ||
|
||
export interface DeleteUserTokenOpts { | ||
user_id: string; | ||
token: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters