Skip to main content
Glama

Superglue MCP

Official
by superglue-ai
encryption.test.ts7.17 kB
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { CredentialEncryption } from './encryption.js'; describe('CredentialEncryption', () => { let originalEnv: NodeJS.ProcessEnv; beforeEach(() => { originalEnv = process.env; process.env = { ...originalEnv }; vi.resetModules(); }); afterEach(() => { process.env = originalEnv; }); describe('when MASTER_ENCRYPTION_KEY is not set', () => { beforeEach(() => { delete process.env.MASTER_ENCRYPTION_KEY; }); it('should return credentials unchanged', () => { const encryption = new CredentialEncryption(); const credentials = { apiKey: 'sk_test_123', secret: 'my-secret-value' }; const encrypted = encryption.encrypt(credentials); expect(encrypted).toEqual(credentials); const decrypted = encryption.decrypt(encrypted); expect(decrypted).toEqual(credentials); }); it('should handle null/undefined credentials', () => { const encryption = new CredentialEncryption(); expect(encryption.encrypt(null)).toBeNull(); expect(encryption.encrypt(undefined)).toBeUndefined(); expect(encryption.decrypt(null)).toBeNull(); expect(encryption.decrypt(undefined)).toBeUndefined(); }); }); describe('when MASTER_ENCRYPTION_KEY is set', () => { beforeEach(() => { process.env.MASTER_ENCRYPTION_KEY = 'test-master-key-12345'; }); it('should encrypt and decrypt credentials', () => { const encryption = new CredentialEncryption(); const credentials = { apiKey: 'sk_test_123', secret: 'my-secret-value', token: 'bearer-token-xyz' }; const encrypted = encryption.encrypt(credentials); // Verify values are encrypted expect(encrypted.apiKey).not.toEqual(credentials.apiKey); expect(encrypted.apiKey).toMatch(/^enc:/); expect(encrypted.secret).not.toEqual(credentials.secret); expect(encrypted.secret).toMatch(/^enc:/); expect(encrypted.token).not.toEqual(credentials.token); expect(encrypted.token).toMatch(/^enc:/); // Verify format is enc:iv:encryptedData const parts = encrypted.apiKey.split(':'); expect(parts).toHaveLength(3); expect(parts[0]).toBe('enc'); expect(parts[1]).toHaveLength(32); // 16 bytes as hex = 32 chars // Verify decryption works const decrypted = encryption.decrypt(encrypted); expect(decrypted).toEqual(credentials); }); it('should handle empty values in credentials', () => { const encryption = new CredentialEncryption(); const credentials = { apiKey: 'sk_test_123', emptyValue: '', nullValue: null as any, undefinedValue: undefined as any }; const encrypted = encryption.encrypt(credentials); expect(encrypted.apiKey).toMatch(/^enc:/); expect(encrypted.emptyValue).toBe(''); expect(encrypted.nullValue).toBeNull(); expect(encrypted.undefinedValue).toBeUndefined(); const decrypted = encryption.decrypt(encrypted); expect(decrypted.apiKey).toBe('sk_test_123'); expect(decrypted.emptyValue).toBe(''); }); it('should handle mixed encrypted and plain values', () => { const encryption = new CredentialEncryption(); // Test that plain values pass through unchanged const plainCredentials = { plain: 'plain-text-value', alsoPlain: 'another-plain-value' }; const result = encryption.decrypt(plainCredentials); expect(result.plain).toBe('plain-text-value'); expect(result.alsoPlain).toBe('another-plain-value'); // Test that invalid encrypted format throws const invalidCredentials = { apiKey: 'enc:invalidformat' // Missing third part }; expect(() => encryption.decrypt(invalidCredentials)).toThrow('Failed to decrypt credentials'); }); it('should use different IVs for same value', () => { const encryption = new CredentialEncryption(); const credentials1 = { apiKey: 'same-value' }; const credentials2 = { apiKey: 'same-value' }; const encrypted1 = encryption.encrypt(credentials1); const encrypted2 = encryption.encrypt(credentials2); // Same plaintext should produce different ciphertext due to random IV expect(encrypted1.apiKey).not.toEqual(encrypted2.apiKey); // Extract IVs and verify they're different const iv1 = encrypted1.apiKey.split(':')[1]; const iv2 = encrypted2.apiKey.split(':')[1]; expect(iv1).not.toEqual(iv2); // But both should decrypt to the same value expect(encryption.decrypt(encrypted1)).toEqual(credentials1); expect(encryption.decrypt(encrypted2)).toEqual(credentials2); }); it('should throw error on invalid encrypted data', () => { const encryption = new CredentialEncryption(); const invalidCredentials = { apiKey: 'enc:invalidformat' }; expect(() => encryption.decrypt(invalidCredentials)).toThrow('Failed to decrypt credentials'); }); it('should fail to decrypt with different master key', () => { // Encrypt with one key process.env.MASTER_ENCRYPTION_KEY = 'key-1'; const encryption1 = new CredentialEncryption(); const credentials = { apiKey: 'sk_test_123' }; const encrypted = encryption1.encrypt(credentials); // Try to decrypt with different key process.env.MASTER_ENCRYPTION_KEY = 'key-2'; const encryption2 = new CredentialEncryption(); expect(() => encryption2.decrypt(encrypted)).toThrow('Failed to decrypt credentials'); }); }); describe('isEnabled', () => { it('should return false when no master key', () => { delete process.env.MASTER_ENCRYPTION_KEY; const encryption = new CredentialEncryption(); expect(encryption.isEnabled()).toBe(false); }); it('should return true when master key is set', () => { process.env.MASTER_ENCRYPTION_KEY = 'test-key'; const encryption = new CredentialEncryption(); expect(encryption.isEnabled()).toBe(true); }); }); });

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/superglue-ai/superglue'

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