feat(professors,sms): merge professor with users, add existing user link, professor portal endpoint, and SMS bypass list
This commit is contained in:
@@ -13,17 +13,32 @@ let cache = null;
|
||||
let cacheAt = 0;
|
||||
const CACHE_TTL_MS = 10000;
|
||||
|
||||
const normalizePhoneForBypass = (raw = '') => {
|
||||
if (!raw) return '';
|
||||
let digits = String(raw)
|
||||
.replace(/[۰-۹]/g, (d) => '0123456789'['۰۱۲۳۴۵۶۷۸۹'.indexOf(d)])
|
||||
.replace(/[٠-٩]/g, (d) => '0123456789'['٠١٢٣٤٥٦٧٨٩'.indexOf(d)])
|
||||
.replace(/\D/g, '');
|
||||
if (digits.startsWith('98') && digits.length >= 12) digits = `0${digits.slice(2)}`;
|
||||
if (digits.length === 10 && digits.startsWith('9')) digits = `0${digits}`;
|
||||
if (digits.length > 11 && digits.startsWith('09')) digits = digits.slice(0, 11);
|
||||
return digits;
|
||||
};
|
||||
|
||||
const readDbFlags = (doc) => ({
|
||||
smsEnabled: doc?.smsEnabled,
|
||||
emailEnabled: doc?.emailEnabled,
|
||||
botEnabled: doc?.botEnabled
|
||||
botEnabled: doc?.botEnabled,
|
||||
smsBypassNumbers: Array.isArray(doc?.smsBypassNumbers)
|
||||
? doc.smsBypassNumbers.map((item) => (item.toObject ? item.toObject() : item))
|
||||
: []
|
||||
});
|
||||
|
||||
const getDbMessagingFlags = async () => {
|
||||
const now = Date.now();
|
||||
if (cache && (now - cacheAt) < CACHE_TTL_MS) return cache;
|
||||
const doc = await Setting.findOne({ key: SETTINGS_KEY })
|
||||
.select('smsEnabled emailEnabled botEnabled')
|
||||
.select('smsEnabled emailEnabled botEnabled smsBypassNumbers')
|
||||
.lean();
|
||||
cache = readDbFlags(doc);
|
||||
cacheAt = now;
|
||||
@@ -35,13 +50,42 @@ const invalidateMessagingCache = () => {
|
||||
cacheAt = 0;
|
||||
};
|
||||
|
||||
const getMessagingChannelState = async (channel) => {
|
||||
const isSmsBypassNumber = async (phoneNumber) => {
|
||||
if (!phoneNumber) return false;
|
||||
const target = normalizePhoneForBypass(phoneNumber);
|
||||
if (!target) return false;
|
||||
|
||||
try {
|
||||
const db = await getDbMessagingFlags();
|
||||
const bypassList = Array.isArray(db.smsBypassNumbers) ? db.smsBypassNumbers : [];
|
||||
return bypassList.some((item) => item.isActive !== false && normalizePhoneForBypass(item.phoneNumber) === target);
|
||||
} catch (err) {
|
||||
logger.warn(`[Messaging] Failed to check bypass numbers: ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getMessagingChannelState = async (channel, recipientPhone = null) => {
|
||||
const envEnabled = isEnvChannelEnabled(channel, config);
|
||||
const bypass = channel === 'sms' && recipientPhone ? await isSmsBypassNumber(recipientPhone) : false;
|
||||
|
||||
if (bypass) {
|
||||
logger.info(`[Messaging] Recipient ${recipientPhone} is in SMS bypass list. Channel bypass activated.`);
|
||||
return {
|
||||
enabled: true,
|
||||
envEnabled,
|
||||
dbEnabled: true,
|
||||
bypass: true,
|
||||
blockReason: null
|
||||
};
|
||||
}
|
||||
|
||||
if (!envEnabled) {
|
||||
return {
|
||||
enabled: false,
|
||||
envEnabled: false,
|
||||
dbEnabled: null,
|
||||
bypass: false,
|
||||
blockReason: 'env_disabled'
|
||||
};
|
||||
}
|
||||
@@ -53,6 +97,7 @@ const getMessagingChannelState = async (channel) => {
|
||||
enabled: dbEnabled,
|
||||
envEnabled: true,
|
||||
dbEnabled,
|
||||
bypass: false,
|
||||
blockReason: dbEnabled ? null : 'dashboard_disabled'
|
||||
};
|
||||
} catch (err) {
|
||||
@@ -61,13 +106,14 @@ const getMessagingChannelState = async (channel) => {
|
||||
enabled: true,
|
||||
envEnabled: true,
|
||||
dbEnabled: null,
|
||||
bypass: false,
|
||||
blockReason: null
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const isMessagingChannelEnabled = async (channel) => {
|
||||
const state = await getMessagingChannelState(channel);
|
||||
const isMessagingChannelEnabled = async (channel, recipientPhone = null) => {
|
||||
const state = await getMessagingChannelState(channel, recipientPhone);
|
||||
return state.enabled;
|
||||
};
|
||||
|
||||
@@ -76,6 +122,8 @@ const getPublicMessaging = (doc) => toPublicMessaging(readDbFlags(doc), config);
|
||||
module.exports = {
|
||||
getMessagingChannelState,
|
||||
isMessagingChannelEnabled,
|
||||
isSmsBypassNumber,
|
||||
normalizePhoneForBypass,
|
||||
invalidateMessagingCache,
|
||||
getPublicMessaging,
|
||||
getDbMessagingFlags
|
||||
|
||||
Reference in New Issue
Block a user