You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
Auth before select database (#1679)
* Auth before select database * fix #1681 Co-authored-by: leibale <leibale1998@gmail.com>
This commit is contained in:
@@ -119,6 +119,18 @@ describe('Client', () => {
|
||||
|
||||
assert.equal(client.isOpen, false);
|
||||
});
|
||||
|
||||
itWithClient(TestRedisServers.PASSWORD, 'should execute AUTH before SELECT', async client => {
|
||||
assert.equal(
|
||||
(await client.clientInfo()).db,
|
||||
2
|
||||
);
|
||||
}, {
|
||||
minimumRedisVersion: [6, 2],
|
||||
clientOptions: {
|
||||
database: 2
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('legacyMode', () => {
|
||||
|
@@ -177,24 +177,44 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
||||
|
||||
#initiateSocket(): RedisSocket {
|
||||
const socketInitiator = async (): Promise<void> => {
|
||||
const v4Commands = this.#options?.legacyMode ? this.#v4 : this,
|
||||
promises = [];
|
||||
const promises = [];
|
||||
|
||||
if (this.#selectedDB !== 0) {
|
||||
promises.push(v4Commands.select(RedisClient.commandOptions({ asap: true }), this.#selectedDB));
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
['SELECT', this.#selectedDB.toString()],
|
||||
{ asap: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.#options?.readonly) {
|
||||
promises.push(v4Commands.readonly(RedisClient.commandOptions({ asap: true })));
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
COMMANDS.READONLY.transformArguments(),
|
||||
{ asap: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.#options?.username || this.#options?.password) {
|
||||
promises.push(v4Commands.auth(RedisClient.commandOptions({ asap: true }), this.#options));
|
||||
promises.push(
|
||||
this.#queue.addCommand(
|
||||
COMMANDS.AUTH.transformArguments({
|
||||
username: this.#options.username,
|
||||
password: this.#options.password ?? ''
|
||||
}),
|
||||
{ asap: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const resubscribePromise = this.#queue.resubscribe();
|
||||
if (resubscribePromise) {
|
||||
promises.push(resubscribePromise);
|
||||
}
|
||||
|
||||
if (promises.length) {
|
||||
this.#tick();
|
||||
}
|
||||
|
||||
@@ -410,7 +430,7 @@ export default class RedisClient<M extends RedisModules, S extends RedisScripts>
|
||||
quit = this.QUIT;
|
||||
|
||||
#tick(): void {
|
||||
if (!this.#socket.isSocketExists) {
|
||||
if (!this.#socket.isSocketExists || this.#socket.writableNeedDrain) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -76,6 +76,14 @@ export default class RedisSocket extends EventEmitter {
|
||||
return !!this.#socket;
|
||||
}
|
||||
|
||||
// `writable.writableNeedDrain` was added in v15.2.0 and therefore can't be used
|
||||
// https://nodejs.org/api/stream.html#stream_writable_writableneeddrain
|
||||
#writableNeedDrain = false;
|
||||
|
||||
get writableNeedDrain(): boolean {
|
||||
return this.#writableNeedDrain;
|
||||
}
|
||||
|
||||
constructor(initiator?: RedisSocketInitiator, options?: RedisSocketOptions) {
|
||||
super();
|
||||
|
||||
@@ -163,7 +171,10 @@ export default class RedisSocket extends EventEmitter {
|
||||
this.#onSocketError(new Error('Socket closed unexpectedly'));
|
||||
}
|
||||
})
|
||||
.on('drain', () => this.emit('drain'))
|
||||
.on('drain', () => {
|
||||
this.#writableNeedDrain = false;
|
||||
this.emit('drain');
|
||||
})
|
||||
.on('data', (data: Buffer) => this.emit('data', data));
|
||||
|
||||
resolve(socket);
|
||||
@@ -198,7 +209,9 @@ export default class RedisSocket extends EventEmitter {
|
||||
throw new ClientClosedError();
|
||||
}
|
||||
|
||||
return this.#socket.write(toWrite);
|
||||
const wasFullyWritten = this.#socket.write(toWrite);
|
||||
this.#writableNeedDrain = !wasFullyWritten;
|
||||
return wasFullyWritten;
|
||||
}
|
||||
|
||||
async disconnect(ignoreIsOpen = false): Promise<void> {
|
||||
|
@@ -284,16 +284,23 @@ export function describeHandleMinimumRedisVersion(minimumVersion: PartialRedisVe
|
||||
});
|
||||
}
|
||||
|
||||
interface RedisClientTestOptions extends RedisTestOptions {
|
||||
clientOptions?: RedisClientOptions<{}, {}>;
|
||||
}
|
||||
|
||||
export function itWithClient(
|
||||
type: TestRedisServers,
|
||||
title: string,
|
||||
fn: (client: RedisClientType) => Promise<void>,
|
||||
options?: RedisTestOptions
|
||||
options?: RedisClientTestOptions
|
||||
): void {
|
||||
it(title, async function () {
|
||||
if (handleMinimumRedisVersion(this, options?.minimumRedisVersion)) return;
|
||||
|
||||
const client = RedisClient.create(TEST_REDIS_SERVERS[type]);
|
||||
const client = RedisClient.create({
|
||||
...TEST_REDIS_SERVERS[type],
|
||||
...options?.clientOptions
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
|
Reference in New Issue
Block a user