📧 fix: Restore invite-user CLI (#14436)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
GitNexus Index / index (push) Waiting to run
GitNexus Index / post-index (push) Blocked by required conditions

* fix: restore invite-user CLI

* fix: guard createInvite failure shape in invite-user CLI

createInvite resolves to { message } on error rather than throwing, so the
CLI interpolated it into the register link as [object Object] and emailed
an unusable invite.

* fix: normalize invite email before token creation

findToken lowercases its email query but the Token schema has no lowercase
setter, so a mixed-case address passed to the CLI was stored verbatim and
the resulting invite could never be redeemed.

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
unsnow-iac 2026-07-27 05:35:50 +02:00 committed by GitHub
parent d8427ffc5e
commit 8374b8416a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 27 additions and 3 deletions

View file

@ -0,0 +1,16 @@
jest.mock('../connect', () => jest.fn(() => new Promise(() => {})));
describe('Invite user CLI', () => {
it('loads its runtime dependencies', () => {
const existingHandlers = new Set(process.listeners('uncaughtException'));
try {
expect(() => require('../invite-user')).not.toThrow();
} finally {
process
.listeners('uncaughtException')
.filter((handler) => !existingHandlers.has(handler))
.forEach((handler) => process.removeListener('uncaughtException', handler));
}
});
});

View file

@ -1,10 +1,10 @@
const path = require('path');
const mongoose = require('mongoose');
const { checkEmailConfig } = require('@librechat/api');
const { checkEmailConfig, createInvite } = require('@librechat/api');
const { User } = require('@librechat/data-schemas').createModels(mongoose);
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers');
const { createInvite } = require('~/models/inviteUser');
const { createToken, findToken } = require('~/models');
const { sendEmail } = require('~/server/utils');
const connect = require('./connect');
@ -35,6 +35,9 @@ const connect = require('./connect');
if (!email) {
email = await askQuestion('Email:');
}
/** `findToken` lowercases its email query, but the Token schema has no setter, so an
* un-normalized address here is written verbatim and can never be looked up again. */
email = email.trim().toLowerCase();
// Validate the email
if (!email.includes('@')) {
console.red('Error: Invalid email address!');
@ -48,7 +51,12 @@ const connect = require('./connect');
silentExit(1);
}
const token = await createInvite(email);
const token = await createInvite(email, { createToken, findToken });
if (typeof token !== 'string') {
console.red('Error: Failed to create the invite token!');
silentExit(1);
}
const inviteLink = `${process.env.DOMAIN_CLIENT}/register?token=${token}`;
const appName = process.env.APP_TITLE || 'LibreChat';