Space Usage
Theme Settings
Space settings allow enterprise administrators to customize the workspace theme color to match their brand colors.
Integration Settings
GPTBots allows you to embed the entire workspace into your enterprise mobile app so employees can open it without signing in.
Encrypting the AiToken for an Employee
- Encrypt the employee’s email with the workspace RSA public key (
publicKey
) and Base64-encode the ciphertext. - Concatenate your
projectId
and the Base64 ciphertext with a colon:{projectId}:{base64-encoded-ciphertext}
.
Base64-encode the whole string again; the result is the final encryptedAiToken
. - Build the employee-specific login URL:
{workspace-integration-url}?{AiToken}
. - When the employee opens this URL inside the mobile app, the workspace launches without any login prompt.
- JAVA Encryption Code Example
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
public class Main {
private static final String RSA_ALGORITHM = "RSA";
private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
/**
* Encrypts data using RSA public key.
*
* @param data The data to encrypt.
* @param publicKeyStr The Base64 encoded RSA public key.
* @return Encrypted data bytes.
*/
public static byte[] encrypt(byte[] data, String publicKeyStr) throws Exception {
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* Generates a login key by encrypting the email and combining with projectId.
*
* @param projectId The project ID.
* @param email The user's email.
* @param publicKey The Base64 encoded RSA public key.
* @return The final login key string.
* @throws Exception if encryption fails.
*/
public static String generateLoginKey(String projectId, String email, String publicKey) throws Exception {
byte[] emailEncrypted = encrypt(email.getBytes(StandardCharsets.UTF_8), publicKey);
String emailRSAStr = Base64.getEncoder().encodeToString(emailEncrypted);
String keyStr = projectId + ":" + emailRSAStr;
return Base64.getEncoder().encodeToString(keyStr.getBytes(StandardCharsets.UTF_8));
}
public static void main(String[] args) {
String projectId = "your project ID";
String email = "your email";
String publicKey = "your public key";
try {
String key = generateLoginKey(projectId, email, publicKey);
System.out.println(key);
} catch (Exception e) {
System.err.println("Failed to generate login key: " + e.getMessage());
}
}
}
- TypeScript Encryption Code Example
import * as forge from 'node-forge';
/**
* Encrypt data using RSA public key
* @param data Data to be encrypted
* @param publicKeyStr Base64 encoded public key string
* @returns Encrypted byte array
*/
export function encrypt(data: string, publicKeyStr: string): Uint8Array {
try {
// Decode Base64 public key
const publicKeyBytes = forge.util.decode64(publicKeyStr);
// Create public key object
const publicKey = forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyBytes));
// Use RSA encryption with PKCS1 padding (consistent with Java's default behavior)
const encrypted = publicKey.encrypt(data, 'RSAES-PKCS1-V1_5');
// Convert forge's byte string to Uint8Array
const bytes = new Uint8Array(encrypted.length);
for (let i = 0; i < encrypted.length; i++) {
bytes[i] = encrypted.charCodeAt(i) & 0xff;
}
return bytes;
} catch (error) {
throw new Error(`RSA encryption failed: ${error}`);
}
}
/**
* Convert byte array to Base64 string
* @param bytes Byte array
* @returns Base64 encoded string
*/
export function bytesToBase64(bytes: Uint8Array): string {
// Convert Uint8Array to string, then use forge's encode64
const binaryString = Array.from(bytes, byte => String.fromCharCode(byte)).join('');
return forge.util.encode64(binaryString);
}
/**
* Convert string to Base64
* @param str String to be encoded
* @returns Base64 encoded string
*/
export function stringToBase64(str: string): string {
return forge.util.encode64(str);
}
/**
* Main function - Generate encrypted key string
* @param projectId Project ID
* @param email Email address
* @param publicKey Base64 encoded RSA public key
* @returns Final encrypted Base64 string
*/
export function generateEncryptedKey(projectId: string, email: string, publicKey: string): string {
// Use RSA to encrypt email
const emailRSAEncrypt = encrypt(email, publicKey);
// Convert encryption result to Base64
const emailRSAStr = bytesToBase64(emailRSAEncrypt);
// Combine projectId and encrypted email
const keyStr = `${projectId}:${emailRSAStr}`;
// Encode the entire string with Base64
const result = stringToBase64(keyStr);
return result;
}
// Generate AiToken example
// generateEncryptedKey(projectId, email, publicKey)
APP Workspace Integration
When enterprises need to integrate the workspace within their mobile APP, they can achieve communication between the native app and H5 pages through WebViewBridge. The integration can be implemented according to the following steps:
WebViewBridge is a bridging interface for bidirectional communication between native applications and H5 pages. It provides unified communication protocols and methods, enabling convenient mutual invocation and data transmission between native code and H5 pages.
- For detailed APP integration instructions, please refer to Android Workspace Integration Documentation and iOS Workspace Integration Documentation.
- When enterprise employees access the workspace via the APP, the workspace should be opened with the employee's identity. The access URL generation rule is as follows:
https://gptbots.ai/space/h5/home?AiToken={encryptedAiToken}&hideClose=true
Where {encryptedAiToken} is the AiToken encrypted with the RSA public key, containing the Organization ID and employee account email.
- Configuring the hideClose parameter
hideClose
is an optional parameter used to control whether to hide the "Close" button. If set totrue
, the "Close" button will be hidden on the webview page.- By default, the "Close" button is displayed on the page. Clicking the "Close" button will send a close action notification message via WebViewBridge. Upon receiving this notification, the APP can close the workspace page. The JSON data for the close action notification is as follows:
{
"eventType": "click",
"data": {
"value": "close",
"timestamp": Date.now(),//Timestamp in milliseconds
"extendedData": {} // Optional, extensible key-value pair parameters
}
}
eventType: String, represents the event type, used to identify different functional calls
data: JSON object, contains event-related parameter data, which may include different fields based on eventType
Event Type | Constant | Description | Parameters |
---|---|---|---|
click | EVENT_CLICK | Webview page click event | data: Additional data (optional), JSON format, default includes fields: value (event type, e.g., "click"), timestamp (timestamp in milliseconds) |
message | EVENT_MESSAGE | Webview page message event | data: Additional data (optional), JSON format, default includes fields: value (event type, e.g., "message"), timestamp (timestamp in milliseconds) |