Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change log

## 0.33.0

* Added: Realtime connections now send the configured JWT for authentication.
* Added: Forwarded `impersonateUserId` on `avatars` and `storage` file requests.
* Fixed: URL-encode path parameters across all services.

## 0.32.0

* Breaking: Renamed `Theme` enum to `BrowserTheme`.
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/account/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const account = new Account(client);
const result = await account.create({
userId: '<USER_ID>',
email: 'email@example.com',
password: '',
password: 'password',
name: '<NAME>' // optional
});

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/account/update-password.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const client = new Client()
const account = new Account(client);

const result = await account.updatePassword({
password: '',
oldPassword: '<OLD_PASSWORD>' // optional
password: 'password',
oldPassword: 'password' // optional
Comment on lines +11 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Literal 'password' used as placeholder for both new and old password

Both password and oldPassword are now set to the same literal 'password' string in the example. A developer copying this code verbatim would set both fields to the exact same value and potentially not notice. Using distinct placeholders like '<NEW_PASSWORD>' and '<OLD_PASSWORD>' (matching the pre-existing '<OLD_PASSWORD>' style from the previous version) would make the intent clearer. The same pattern applies to create.md and update-recovery.md.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

});

console.log(result);
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/account/update-recovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const account = new Account(client);
const result = await account.updateRecovery({
userId: '<USER_ID>',
secret: '<SECRET>',
password: ''
password: 'password'
});

console.log(result);
Expand Down
2,636 changes: 949 additions & 1,687 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "react-native-appwrite",
"homepage": "https://appwrite.io/support",
"description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
"version": "0.32.0",
"version": "0.33.0",
"license": "BSD-3-Clause",
"main": "dist/cjs/sdk.js",
"exports": {
Expand Down
35 changes: 12 additions & 23 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class Client {
'x-sdk-name': 'React Native',
'x-sdk-platform': 'client',
'x-sdk-language': 'reactnative',
'x-sdk-version': '0.32.0',
'x-sdk-version': '0.33.0',
'X-Appwrite-Response-Format': '1.9.5',
};

Expand Down Expand Up @@ -345,13 +345,7 @@ class Client {
/**
* Set ImpersonateUserId
*
* Impersonate a user by ID on an already user-authenticated request. Requires
* the current request to be authenticated as a user with impersonator
* capability; X-Appwrite-Key alone is not sufficient. Impersonator users are
* intentionally granted users.read so they can discover a target before
* impersonation begins. Internal audit logs still attribute actions to the
* original impersonator and record the impersonated target only in internal
* audit payload data.
* Impersonate a user by ID
*
* @param value string
*
Expand All @@ -366,13 +360,7 @@ class Client {
/**
* Set ImpersonateUserEmail
*
* Impersonate a user by email on an already user-authenticated request.
* Requires the current request to be authenticated as a user with
* impersonator capability; X-Appwrite-Key alone is not sufficient.
* Impersonator users are intentionally granted users.read so they can
* discover a target before impersonation begins. Internal audit logs still
* attribute actions to the original impersonator and record the impersonated
* target only in internal audit payload data.
* Impersonate a user by email
*
* @param value string
*
Expand All @@ -387,13 +375,7 @@ class Client {
/**
* Set ImpersonateUserPhone
*
* Impersonate a user by phone on an already user-authenticated request.
* Requires the current request to be authenticated as a user with
* impersonator capability; X-Appwrite-Key alone is not sufficient.
* Impersonator users are intentionally granted users.read so they can
* discover a target before impersonation begins. Internal audit logs still
* attribute actions to the original impersonator and record the impersonated
* target only in internal audit payload data.
* Impersonate a user by phone
*
* @param value string
*
Expand Down Expand Up @@ -458,6 +440,11 @@ class Client {
const channels = new URLSearchParams();
channels.set('project', this.config.project);

const jwt = this.config.jwt;
if (jwt && Platform.OS === 'web') {
channels.set('jwt', jwt);
}

const url = this.config.endpointRealtime + '/realtime?' + channels.toString();

if (
Expand All @@ -477,7 +464,8 @@ class Client {
// @ts-ignore
this.realtime.socket = new WebSocket(url, undefined, {
headers: {
Origin: `appwrite-${Platform.OS}://${this.config.platform}`
Origin: `appwrite-${Platform.OS}://${this.config.platform}`,
...(jwt && Platform.OS !== 'web' ? { 'x-appwrite-jwt': jwt } : {})
}
});
this.realtime.socket.addEventListener('message', this.realtime.onMessage);
Expand Down Expand Up @@ -678,6 +666,7 @@ class Client {
async ping(): Promise<unknown> {
return this.call('GET', new URL(this.config.endpoint + '/ping'), {
'X-Appwrite-Project': this.config.project,
'accept': 'application/json',
});
}

Expand Down
28 changes: 14 additions & 14 deletions src/services/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "identityId"');
}

const apiPath = '/account/identities/{identityId}'.replace('{identityId}', identityId);
const apiPath = '/account/identities/{identityId}'.replace('{identityId}', encodeURIComponent(String(identityId)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -476,7 +476,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "type"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -523,7 +523,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "type"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -580,7 +580,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "otp"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

if (typeof otp !== 'undefined') {
Expand Down Expand Up @@ -640,7 +640,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "otp"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

if (typeof otp !== 'undefined') {
Expand Down Expand Up @@ -692,7 +692,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "type"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -738,7 +738,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "type"');
}

const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
const apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', encodeURIComponent(String(type)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -1755,7 +1755,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "provider"');
}

const apiPath = '/account/sessions/oauth2/{provider}'.replace('{provider}', provider);
const apiPath = '/account/sessions/oauth2/{provider}'.replace('{provider}', encodeURIComponent(String(provider)));
const payload: Payload = {};

if (typeof success !== 'undefined') {
Expand Down Expand Up @@ -1945,7 +1945,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "sessionId"');
}

const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', sessionId);
const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', encodeURIComponent(String(sessionId)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -1991,7 +1991,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "sessionId"');
}

const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', sessionId);
const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', encodeURIComponent(String(sessionId)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -2038,7 +2038,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "sessionId"');
}

const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', sessionId);
const apiPath = '/account/sessions/{sessionId}'.replace('{sessionId}', encodeURIComponent(String(sessionId)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -2183,7 +2183,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "identifier"');
}

const apiPath = '/account/targets/{targetId}/push'.replace('{targetId}', targetId);
const apiPath = '/account/targets/{targetId}/push'.replace('{targetId}', encodeURIComponent(String(targetId)));
const payload: Payload = {};

if (typeof identifier !== 'undefined') {
Expand Down Expand Up @@ -2234,7 +2234,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "targetId"');
}

const apiPath = '/account/targets/{targetId}/push'.replace('{targetId}', targetId);
const apiPath = '/account/targets/{targetId}/push'.replace('{targetId}', encodeURIComponent(String(targetId)));
const payload: Payload = {};

const uri = new URL(this.client.config.endpoint + apiPath);
Expand Down Expand Up @@ -2465,7 +2465,7 @@ export class Account extends Service {
throw new AppwriteException('Missing required parameter: "provider"');
}

const apiPath = '/account/tokens/oauth2/{provider}'.replace('{provider}', provider);
const apiPath = '/account/tokens/oauth2/{provider}'.replace('{provider}', encodeURIComponent(String(provider)));
const payload: Payload = {};

if (typeof success !== 'undefined') {
Expand Down
Loading
Loading