onairos
Version:
The Onairos Library is a collection of functions that enable Applications to connect and communicate data with Onairos Identities via User Authorization. Integration for developers is seamless, simple and effective for all applications. LLM SDK capabiliti
594 lines (524 loc) • 21 kB
JavaScript
import { User } from '../../Mongoose/models.js';
import { getEnochModels, connectEnochDB } from '../../utils/enochDb.js';
export class DatabaseUtils {
constructor() {
this.databases = {
ENOCH: 'enoch',
ONAIROS: 'onairos'
};
}
/**
* Find user across both databases
* @param {string} identifier - Username, email, or user ID
* @param {string} preferredDb - Preferred database to check first
* @returns {object} - User object with database info
*/
async findUser(identifier, preferredDb = null) {
try {
console.log(`🔍 [DB-UTILS] Looking for user: ${identifier}`);
let user = null;
let userType = null;
let searchResults = {
enochSearched: false,
onairosSearched: false,
enochFound: false,
onairosFound: false
};
// Determine search order
const searchOrder = preferredDb === this.databases.ENOCH ?
['enoch', 'onairos'] : ['onairos', 'enoch'];
for (const dbType of searchOrder) {
if (dbType === 'enoch' && !searchResults.enochSearched) {
try {
await connectEnochDB();
const { EnochUser } = getEnochModels();
// Try multiple search methods for Enoch
user = await EnochUser.findById(identifier) ||
await EnochUser.findOne({ email: identifier }) ||
await EnochUser.findOne({ name: identifier }) ||
await EnochUser.findOne({ enochEmail: identifier });
searchResults.enochSearched = true;
if (user) {
userType = this.databases.ENOCH;
searchResults.enochFound = true;
console.log(`✅ [DB-UTILS] Found Enoch user: ${user.name || user.email}`);
break;
}
} catch (enochError) {
console.warn(`⚠️ [DB-UTILS] Enoch database error:`, enochError.message);
searchResults.enochSearched = true;
}
} else if (dbType === 'onairos' && !searchResults.onairosSearched) {
try {
// Try multiple search methods for Onairos
user = await User.findById(identifier) ||
await User.findOne({ userName: identifier }) ||
await User.findOne({ email: identifier });
searchResults.onairosSearched = true;
if (user) {
userType = this.databases.ONAIROS;
searchResults.onairosFound = true;
console.log(`✅ [DB-UTILS] Found Onairos user: ${user.userName || user.email}`);
break;
}
} catch (onairosError) {
console.warn(`⚠️ [DB-UTILS] Onairos database error:`, onairosError.message);
searchResults.onairosSearched = true;
}
}
}
return {
user,
userType,
isEnochUser: userType === this.databases.ENOCH,
searchResults,
foundIn: userType,
searchedIn: Object.keys(searchResults).filter(key => searchResults[key] && key.endsWith('Searched')).map(key => key.replace('Searched', ''))
};
} catch (error) {
console.error(`❌ [DB-UTILS] Error finding user:`, error);
return {
user: null,
userType: null,
isEnochUser: false,
error: error.message
};
}
}
/**
* Get user's platform connections from appropriate database
* @param {object} user - User object
* @param {string} userType - User type (enoch or onairos)
* @returns {object} - Platform connections
*/
getUserConnections(user, userType) {
if (!user) return {};
try {
if (userType === this.databases.ENOCH) {
// Extract connections from Enoch user format
const connections = {};
// YouTube
if (user.youtubeAccessToken) {
connections.youtube = {
connected: true,
accessToken: user.youtubeAccessToken,
refreshToken: user.youtubeRefreshToken,
tokenExpiry: user.youtubeTokenExpiry,
channelName: user.youtubeChannelName,
channelId: user.youtubeChannelId,
connectedAt: user.youtubeConnectedAt,
lastValidated: user.youtubeLastValidated
};
}
// LinkedIn
if (user.linkedinAccessToken) {
connections.linkedin = {
connected: true,
accessToken: user.linkedinAccessToken,
refreshToken: user.linkedinRefreshToken,
tokenExpiry: user.linkedinTokenExpiry,
userName: user.linkedinUserName,
connectedAt: user.linkedinConnectedAt,
lastValidated: user.linkedinLastValidated
};
}
// Add other platforms as needed
return connections;
} else {
// Onairos user format
const connections = {};
if (user.accounts) {
Object.keys(user.accounts).forEach(platform => {
if (user.accounts[platform] && user.accounts[platform].accessToken) {
connections[platform] = {
connected: true,
...user.accounts[platform]
};
}
});
}
return connections;
}
} catch (error) {
console.error(`❌ [DB-UTILS] Error getting user connections:`, error);
return {};
}
}
/**
* Update user's platform connection in appropriate database
* @param {object} user - User object
* @param {string} userType - User type
* @param {string} platform - Platform name
* @param {object} connectionData - Connection data to update
* @returns {boolean} - Success status
*/
async updateUserConnection(user, userType, platform, connectionData) {
try {
console.log(`🔄 [DB-UTILS] Updating ${platform} connection for user: ${user._id}`);
if (userType === this.databases.ENOCH) {
const { EnochUser } = getEnochModels();
const updateData = {};
// Map platform data to Enoch format
switch (platform) {
case 'youtube':
if (connectionData.accessToken) updateData.youtubeAccessToken = connectionData.accessToken;
if (connectionData.refreshToken) updateData.youtubeRefreshToken = connectionData.refreshToken;
if (connectionData.tokenExpiry) updateData.youtubeTokenExpiry = connectionData.tokenExpiry;
if (connectionData.channelName) updateData.youtubeChannelName = connectionData.channelName;
if (connectionData.channelId) updateData.youtubeChannelId = connectionData.channelId;
if (connectionData.connectedAt) updateData.youtubeConnectedAt = connectionData.connectedAt;
updateData.youtubeLastValidated = new Date();
break;
case 'linkedin':
if (connectionData.accessToken) updateData.linkedinAccessToken = connectionData.accessToken;
if (connectionData.refreshToken) updateData.linkedinRefreshToken = connectionData.refreshToken;
if (connectionData.tokenExpiry) updateData.linkedinTokenExpiry = connectionData.tokenExpiry;
if (connectionData.userName) updateData.linkedinUserName = connectionData.userName;
if (connectionData.connectedAt) updateData.linkedinConnectedAt = connectionData.connectedAt;
updateData.linkedinLastValidated = new Date();
break;
default:
console.warn(`⚠️ [DB-UTILS] Unsupported platform for Enoch: ${platform}`);
return false;
}
updateData.updatedAt = new Date();
const result = await EnochUser.updateOne(
{ _id: user._id },
{ $set: updateData }
);
console.log(`✅ [DB-UTILS] Updated ${platform} in Enoch database:`, result.modifiedCount > 0);
return result.modifiedCount > 0;
} else {
// Onairos user format
if (!user.accounts) user.accounts = {};
if (!user.accounts[platform]) user.accounts[platform] = {};
Object.assign(user.accounts[platform], connectionData);
user.accounts[platform].lastValidated = new Date();
// Update connections field if needed
if (!user.connections) user.connections = {};
if (!user.connections[platform.charAt(0).toUpperCase() + platform.slice(1)]) {
user.connections[platform.charAt(0).toUpperCase() + platform.slice(1)] = '-';
}
await user.save();
console.log(`✅ [DB-UTILS] Updated ${platform} in Onairos database`);
return true;
}
} catch (error) {
console.error(`❌ [DB-UTILS] Error updating user connection:`, error);
return false;
}
}
/**
* Remove user's platform connection from appropriate database
* @param {object} user - User object
* @param {string} userType - User type
* @param {string} platform - Platform name
* @returns {boolean} - Success status
*/
async removeUserConnection(user, userType, platform) {
try {
console.log(`🗑️ [DB-UTILS] Removing ${platform} connection for user: ${user._id}`);
if (userType === this.databases.ENOCH) {
const { EnochUser } = getEnochModels();
const unsetData = {};
// Map platform data to Enoch format
switch (platform) {
case 'youtube':
unsetData.youtubeAccessToken = "";
unsetData.youtubeRefreshToken = "";
unsetData.youtubeTokenExpiry = "";
unsetData.youtubeChannelName = "";
unsetData.youtubeChannelId = "";
unsetData.youtubeConnectedAt = "";
unsetData.youtubeLastValidated = "";
break;
case 'linkedin':
unsetData.linkedinAccessToken = "";
unsetData.linkedinRefreshToken = "";
unsetData.linkedinTokenExpiry = "";
unsetData.linkedinUserName = "";
unsetData.linkedinConnectedAt = "";
unsetData.linkedinLastValidated = "";
break;
default:
console.warn(`⚠️ [DB-UTILS] Unsupported platform for Enoch: ${platform}`);
return false;
}
const result = await EnochUser.updateOne(
{ _id: user._id },
{
$unset: unsetData,
$set: { updatedAt: new Date() }
}
);
console.log(`✅ [DB-UTILS] Removed ${platform} from Enoch database:`, result.modifiedCount > 0);
return result.modifiedCount > 0;
} else {
// Onairos user format
const result = await User.updateOne(
{ _id: user._id },
{
$unset: { [`accounts.${platform}`]: "" },
$set: { [`connections.${platform.charAt(0).toUpperCase() + platform.slice(1)}`]: "-" }
}
);
console.log(`✅ [DB-UTILS] Removed ${platform} from Onairos database:`, result.modifiedCount > 0);
return result.modifiedCount > 0;
}
} catch (error) {
console.error(`❌ [DB-UTILS] Error removing user connection:`, error);
return false;
}
}
/**
* Get users with specific platform connections
* @param {string} platform - Platform name
* @param {object} filters - Additional filters
* @returns {array} - Array of users with platform connections
*/
async getUsersWithPlatformConnections(platform, filters = {}) {
try {
console.log(`🔍 [DB-UTILS] Finding users with ${platform} connections`);
const users = [];
// Search Enoch database
try {
await connectEnochDB();
const { EnochUser } = getEnochModels();
let enochQuery = {};
switch (platform) {
case 'youtube':
enochQuery.youtubeAccessToken = { $exists: true, $ne: null };
if (filters.hasRefreshToken) {
enochQuery.youtubeRefreshToken = { $exists: true, $ne: null };
}
if (filters.needsRefresh === false) {
enochQuery.youtubeRefreshToken = { $exists: false };
}
break;
case 'linkedin':
enochQuery.linkedinAccessToken = { $exists: true, $ne: null };
if (filters.hasRefreshToken) {
enochQuery.linkedinRefreshToken = { $exists: true, $ne: null };
}
if (filters.needsRefresh === false) {
enochQuery.linkedinRefreshToken = { $exists: false };
}
break;
}
const enochUsers = await EnochUser.find(enochQuery).select('name email');
enochUsers.forEach(user => {
users.push({
_id: user._id,
identifier: user.name || user.email,
email: user.email,
userType: this.databases.ENOCH,
platform: platform
});
});
console.log(`✅ [DB-UTILS] Found ${enochUsers.length} Enoch users with ${platform}`);
} catch (enochError) {
console.warn(`⚠️ [DB-UTILS] Enoch search error:`, enochError.message);
}
// Search Onairos database
try {
let onairosQuery = {};
onairosQuery[`accounts.${platform}.accessToken`] = { $exists: true, $ne: null };
if (filters.hasRefreshToken) {
onairosQuery[`accounts.${platform}.refreshToken`] = { $exists: true, $ne: null };
}
if (filters.needsRefresh === false) {
onairosQuery[`accounts.${platform}.refreshToken`] = { $exists: false };
}
const onairosUsers = await User.find(onairosQuery).select('userName email');
onairosUsers.forEach(user => {
users.push({
_id: user._id,
identifier: user.userName || user.email,
email: user.email,
userType: this.databases.ONAIROS,
platform: platform
});
});
console.log(`✅ [DB-UTILS] Found ${onairosUsers.length} Onairos users with ${platform}`);
} catch (onairosError) {
console.warn(`⚠️ [DB-UTILS] Onairos search error:`, onairosError.message);
}
console.log(`✅ [DB-UTILS] Total users found: ${users.length}`);
return users;
} catch (error) {
console.error(`❌ [DB-UTILS] Error finding users with platform connections:`, error);
return [];
}
}
/**
* Create user account synchronization between databases
* @param {object} sourceUser - Source user object
* @param {string} sourceType - Source database type
* @param {string} targetType - Target database type
* @returns {object} - Sync result
*/
async syncUserBetweenDatabases(sourceUser, sourceType, targetType) {
try {
console.log(`🔄 [DB-UTILS] Syncing user between databases: ${sourceType} -> ${targetType}`);
if (sourceType === targetType) {
return {
success: false,
error: 'Source and target databases are the same'
};
}
const userEmail = sourceUser.email || sourceUser.enochEmail;
const userName = sourceUser.name || sourceUser.userName;
if (!userEmail && !userName) {
return {
success: false,
error: 'User must have email or username for synchronization'
};
}
let targetUser = null;
let created = false;
if (targetType === this.databases.ENOCH) {
// Sync to Enoch database
const { EnochUser } = getEnochModels();
targetUser = await EnochUser.findOne({
$or: [
{ email: userEmail },
{ name: userName },
{ enochEmail: userEmail }
]
});
if (!targetUser) {
targetUser = new EnochUser({
_id: sourceUser._id,
email: userEmail,
name: userName,
enochEmail: userEmail,
createdAt: new Date(),
updatedAt: new Date()
});
await targetUser.save();
created = true;
}
} else {
// Sync to Onairos database
targetUser = await User.findOne({
$or: [
{ email: userEmail },
{ userName: userName },
{ _id: sourceUser._id }
]
});
if (!targetUser) {
targetUser = new User({
_id: sourceUser._id,
email: userEmail,
userName: userName || userEmail,
accounts: {},
connections: {},
createdAt: new Date(),
updatedAt: new Date()
});
await targetUser.save();
created = true;
}
}
return {
success: true,
created: created,
targetUser: targetUser,
message: created ? 'User created in target database' : 'User already exists in target database'
};
} catch (error) {
console.error(`❌ [DB-UTILS] Error syncing user between databases:`, error);
return {
success: false,
error: error.message
};
}
}
/**
* Get database statistics
* @returns {object} - Database statistics
*/
async getDatabaseStats() {
try {
const stats = {
enoch: {
available: false,
totalUsers: 0,
usersWithConnections: 0,
platformBreakdown: {}
},
onairos: {
available: false,
totalUsers: 0,
usersWithConnections: 0,
platformBreakdown: {}
}
};
// Enoch database stats
try {
await connectEnochDB();
const { EnochUser } = getEnochModels();
stats.enoch.available = true;
stats.enoch.totalUsers = await EnochUser.countDocuments();
// Count users with YouTube connections
const youtubeCount = await EnochUser.countDocuments({
youtubeAccessToken: { $exists: true, $ne: null }
});
stats.enoch.platformBreakdown.youtube = youtubeCount;
// Count users with LinkedIn connections
const linkedinCount = await EnochUser.countDocuments({
linkedinAccessToken: { $exists: true, $ne: null }
});
stats.enoch.platformBreakdown.linkedin = linkedinCount;
stats.enoch.usersWithConnections = await EnochUser.countDocuments({
$or: [
{ youtubeAccessToken: { $exists: true, $ne: null } },
{ linkedinAccessToken: { $exists: true, $ne: null } }
]
});
} catch (enochError) {
console.warn(`⚠️ [DB-UTILS] Enoch stats error:`, enochError.message);
}
// Onairos database stats
try {
stats.onairos.available = true;
stats.onairos.totalUsers = await User.countDocuments();
// Count users with platform connections
const platformCounts = await User.aggregate([
{ $match: { accounts: { $exists: true } } },
{ $project: {
accountKeys: { $objectToArray: "$accounts" }
}},
{ $unwind: "$accountKeys" },
{ $group: {
_id: "$accountKeys.k",
count: { $sum: 1 }
}}
]);
platformCounts.forEach(platform => {
stats.onairos.platformBreakdown[platform._id] = platform.count;
});
stats.onairos.usersWithConnections = await User.countDocuments({
accounts: { $exists: true, $ne: {} }
});
} catch (onairosError) {
console.warn(`⚠️ [DB-UTILS] Onairos stats error:`, onairosError.message);
}
return {
success: true,
stats: stats,
generatedAt: new Date().toISOString()
};
} catch (error) {
console.error(`❌ [DB-UTILS] Error getting database stats:`, error);
return {
success: false,
error: error.message
};
}
}
}
// Export singleton instance
export const databaseUtils = new DatabaseUtils();
export default databaseUtils;