Skip to main content
Glama
credential-manager.ts5.85 kB
import { createHash } from "crypto"; import { logger } from "./logger.js"; export interface StoredCredentials { emailHash: string; timestamp: number; sessionValid: boolean; } export class CredentialManager { private credentialStore: Map<string, StoredCredentials> = new Map(); private readonly SESSION_TIMEOUT = 2 * 60 * 60 * 1000; // 2 hours /** * Hash email for secure storage (one-way hash) */ private hashEmail(email: string): string { return createHash("sha256").update(email).digest("hex"); } /** * Validate email format for N High School Group */ validateEmail(email: string): { valid: boolean; userType: "student" | "staff" | "parent" | "unknown"; message?: string; } { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { return { valid: false, userType: "unknown", message: "Invalid email format", }; } const domain = email.split("@")[1].toLowerCase(); // N High School Group domains if (domain === "nnn.ed.jp") { return { valid: true, userType: "student" }; } else if (domain === "nnn.ac.jp") { return { valid: true, userType: "staff" }; } else if ( domain === "gmail.com" || domain === "yahoo.com" || domain === "outlook.com" || domain === "hotmail.com" ) { return { valid: true, userType: "parent" }; } else { return { valid: true, userType: "parent" }; // Allow other domains for parents } } /** * Store session info after successful login */ storeSession(email: string): void { const emailHash = this.hashEmail(email); const stored: StoredCredentials = { emailHash, timestamp: Date.now(), sessionValid: true, }; this.credentialStore.set(emailHash, stored); logger.info(`Session stored for user: ${email.split("@")[0]}@***`); } /** * Check if user has a valid recent session */ hasValidSession(email: string): boolean { const emailHash = this.hashEmail(email); const stored = this.credentialStore.get(emailHash); if (!stored) { return false; } const isExpired = Date.now() - stored.timestamp > this.SESSION_TIMEOUT; if (isExpired) { this.credentialStore.delete(emailHash); return false; } return stored.sessionValid; } /** * Invalidate session */ invalidateSession(email: string): void { const emailHash = this.hashEmail(email); this.credentialStore.delete(emailHash); logger.info(`Session invalidated for user: ${email.split("@")[0]}@***`); } /** * Get login guidance based on user type */ getLoginGuidance( userType: "student" | "staff" | "parent" | "unknown", ): string { switch (userType) { case "student": return ` [STUDENT] Student Login Guide: - Use your @nnn.ed.jp email address - Use your N High School password - If you have 2FA enabled, you'll need to complete it during login - Contact your homeroom teacher if you've forgotten your password`; case "staff": return ` [STAFF] Staff Login Guide: - Use your @nnn.ac.jp email address - Use your N High School staff password - If you have 2FA enabled, you'll need to complete it during login - Contact IT support if you're having trouble accessing your account`; case "parent": return ` [PARENT] Parent Login Guide: - Use the email address registered with your child's school account - Use the password you set when creating your parent account - If you haven't created a parent account yet, contact your child's school - If you've forgotten your password, use the password reset option`; default: return ` [LOGIN] General Login Guide: - Use your registered email address - Use your N Lobby password - If you have 2FA enabled, you'll need to complete it during login - Contact support if you're having trouble`; } } /** * Get troubleshooting tips for common issues */ getTroubleshootingTips(): string { return ` [TIPS] Common Login Issues & Solutions: 1. **Wrong Email/Password** - Double-check your email address and password - Make sure Caps Lock is off - Try typing your password in a text editor first 2. **2FA Issues** - Make sure your authenticator app is synced - Try using backup codes if available - Wait for the next code if the current one doesn't work 3. **Browser Issues** - Clear your browser cache and cookies - Try using incognito/private mode - Disable browser extensions temporarily 4. **Account Locked** - Wait 15-30 minutes before trying again - Contact support if your account is suspended 5. **Network Issues** - Check your internet connection - Try using a different network or VPN - Make sure N Lobby isn't blocked by your firewall [PRO-TIP] Pro Tips: - Use 'interactive_login' if automated login fails - The browser window will stay open for manual completion - You can close the browser once login is complete`; } /** * Clean up expired sessions */ cleanupExpiredSessions(): void { const now = Date.now(); let cleanedCount = 0; for (const [hash, stored] of this.credentialStore.entries()) { if (now - stored.timestamp > this.SESSION_TIMEOUT) { this.credentialStore.delete(hash); cleanedCount++; } } if (cleanedCount > 0) { logger.info(`Cleaned up ${cleanedCount} expired sessions`); } } /** * Get session statistics */ getSessionStats(): { total: number; expired: number } { const now = Date.now(); let expired = 0; for (const stored of this.credentialStore.values()) { if (now - stored.timestamp > this.SESSION_TIMEOUT) { expired++; } } return { total: this.credentialStore.size, expired, }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/minagishl/nlobby-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server