mirror of
https://github.com/appwrite/appwrite
synced 2026-04-25 07:27:16 +00:00
336 lines
No EOL
9.1 KiB
JavaScript
336 lines
No EOL
9.1 KiB
JavaScript
import http from 'k6/http';
|
|
import { check } from 'k6';
|
|
|
|
/**
|
|
* @typedef {Object} AuthHeaders
|
|
* @property {string} 'Content-Type' - Content type header
|
|
* @property {string} 'Cookie' - Session cookie
|
|
* @property {string} 'X-Appwrite-Project' - Project ID header
|
|
*/
|
|
|
|
/**
|
|
* @typedef {Object} ApiHeaders
|
|
* @property {string} 'Content-Type' - Content type header
|
|
* @property {string} 'X-Appwrite-Project' - Project ID header
|
|
* @property {string} 'X-Appwrite-Key' - API key header
|
|
*/
|
|
|
|
/**
|
|
* @typedef {Object} ProvisionedResources
|
|
* @property {string} userId - The ID of the created user
|
|
* @property {string} teamId - The ID of the created team
|
|
* @property {string} projectId - The ID of the created project
|
|
* @property {string} cookies - Session cookies for authentication
|
|
* @property {AuthHeaders} headers - Headers for cookie-based authentication
|
|
* @property {string} apiKey - The API key secret
|
|
* @property {ApiHeaders} apiHeaders - Headers for API key authentication
|
|
*/
|
|
|
|
function assert(response, checkName, condition) {
|
|
const result = check(response, {
|
|
[checkName]: condition
|
|
});
|
|
if (!result) {
|
|
console.error(`Assertion failed: ${checkName}`);
|
|
console.error(`Response status: ${response.status}`);
|
|
console.error(`Response body: ${response.body}`);
|
|
throw new Error(`Assertion failed: ${checkName}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Provisions an Appwrite project setup including:
|
|
* - Account creation
|
|
* - Session creation
|
|
* - Team creation
|
|
* - Project creation
|
|
* - API Key creation
|
|
*
|
|
* @param {Object} config Configuration object
|
|
* @param {string} config.endpoint Base endpoint URL (e.g., 'http://localhost:80/v1')
|
|
* @param {string} config.email Email for account creation
|
|
* @param {string} config.password Password for account creation
|
|
* @param {string} config.name Name for account creation
|
|
* @param {string} config.projectName Name for the project
|
|
* @returns {ProvisionedResources} Object containing all created resource IDs and session information
|
|
*/
|
|
export function provisionProject(config) {
|
|
const {
|
|
endpoint,
|
|
email,
|
|
password,
|
|
name,
|
|
projectName,
|
|
} = config;
|
|
|
|
// Step 1: Create Account
|
|
const accountResponse = http.post(`${endpoint}/account`, JSON.stringify({
|
|
userId: 'unique()',
|
|
email,
|
|
password,
|
|
name
|
|
}), {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
|
|
assert(accountResponse, 'account created successfully', (r) => r.status === 201 || r.status === 409);
|
|
|
|
const userId = accountResponse.json('$id');
|
|
|
|
// Step 2: Create Session
|
|
const sessionResponse = http.post(`${endpoint}/account/sessions/email`, JSON.stringify({
|
|
email,
|
|
password
|
|
}), {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
|
|
assert(sessionResponse, 'session created successfully', (r) => r.status === 201);
|
|
|
|
// Keep manual control of the cookies to allow for simultaneous requests
|
|
const jar = http.cookieJar();
|
|
jar.clear(`${endpoint}`);
|
|
|
|
// Extract cookies for subsequent requests
|
|
const cookies = sessionResponse.headers['Set-Cookie'];
|
|
|
|
// Common headers for authenticated requests
|
|
const authHeaders = {
|
|
'Content-Type': 'application/json',
|
|
'Cookie': cookies
|
|
};
|
|
|
|
// Step 3: Create Team
|
|
const teamResponse = http.post(`${endpoint}/teams`, JSON.stringify({
|
|
teamId: 'unique()',
|
|
name: `${projectName} Team`
|
|
}), {
|
|
headers: authHeaders
|
|
});
|
|
|
|
assert(teamResponse, 'team created successfully', (r) => r.status === 201);
|
|
|
|
const teamId = teamResponse.json('$id');
|
|
|
|
// Step 4: Create Project
|
|
const projectResponse = http.post(`${endpoint}/projects`, JSON.stringify({
|
|
projectId: 'unique()',
|
|
name: projectName,
|
|
teamId: teamId
|
|
}), {
|
|
headers: authHeaders
|
|
});
|
|
|
|
assert(projectResponse, 'project created successfully', (r) => r.status === 201);
|
|
|
|
const projectId = projectResponse.json('$id');
|
|
|
|
// Step 5: Create API Key
|
|
const apiKeyResponse = http.post(`${endpoint}/projects/${projectId}/keys`, JSON.stringify({
|
|
name: 'Test API Key',
|
|
scopes: SCOPES, // All permissions
|
|
}), {
|
|
headers: authHeaders
|
|
});
|
|
|
|
assert(apiKeyResponse, 'api key created successfully', (r) => r.status === 201);
|
|
|
|
const apiKey = apiKeyResponse.json('secret');
|
|
|
|
// Create a new headers object for API key authentication
|
|
const apiHeaders = {
|
|
'Content-Type': 'application/json',
|
|
'X-Appwrite-Project': projectId,
|
|
'X-Appwrite-Key': apiKey
|
|
};
|
|
|
|
// Return all created resources and session info
|
|
return {
|
|
endpoint,
|
|
userId,
|
|
teamId,
|
|
projectId,
|
|
cookies,
|
|
headers: authHeaders,
|
|
apiKey,
|
|
apiHeaders
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Example usage:
|
|
*
|
|
* const config = {
|
|
* endpoint: 'http://localhost:80/v1',
|
|
* email: '[email protected]',
|
|
* password: 'complex-password',
|
|
* name: 'Test User',
|
|
* projectName: 'Test Project'
|
|
* };
|
|
*
|
|
* const resources = provisionProject(config);
|
|
*/
|
|
|
|
const SCOPES = [
|
|
"sessions.write",
|
|
"users.read",
|
|
"users.write",
|
|
"teams.read",
|
|
"teams.write",
|
|
"databases.read",
|
|
"databases.write",
|
|
"collections.read",
|
|
"collections.write",
|
|
"attributes.read",
|
|
"attributes.write",
|
|
"indexes.read",
|
|
"indexes.write",
|
|
"documents.read",
|
|
"documents.write",
|
|
"files.read",
|
|
"files.write",
|
|
"buckets.read",
|
|
"buckets.write",
|
|
"functions.read",
|
|
"functions.write",
|
|
"execution.read",
|
|
"execution.write",
|
|
"targets.read",
|
|
"targets.write",
|
|
"providers.read",
|
|
"providers.write",
|
|
"messages.read",
|
|
"messages.write",
|
|
"topics.read",
|
|
"topics.write",
|
|
"subscribers.read",
|
|
"subscribers.write",
|
|
"locale.read",
|
|
"avatars.read",
|
|
"health.read",
|
|
"migrations.read",
|
|
"migrations.write"
|
|
]
|
|
|
|
export function provisionDatabase(config) {
|
|
const {
|
|
endpoint,
|
|
apiHeaders
|
|
} = config;
|
|
|
|
// Create database
|
|
const databaseResponse = http.post(
|
|
`${endpoint}/databases`,
|
|
JSON.stringify({
|
|
databaseId: 'unique()',
|
|
name: 'Bulk Test DB'
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(databaseResponse, 'database created successfully', (r) => r.status === 201);
|
|
|
|
const databaseId = databaseResponse.json('$id');
|
|
|
|
// Create collection
|
|
const collectionResponse = http.post(
|
|
`${endpoint}/databases/${databaseId}/collections`,
|
|
JSON.stringify({
|
|
collectionId: 'unique()',
|
|
name: 'Bulk Test Collection',
|
|
permissions: ['read("any")', 'write("any")'],
|
|
documentSecurity: false
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(collectionResponse, 'collection created successfully', (r) => r.status === 201);
|
|
|
|
const collectionId = collectionResponse.json('$id');
|
|
|
|
// Create name attribute
|
|
const nameAttributeResponse = http.post(
|
|
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/string`,
|
|
JSON.stringify({
|
|
key: 'name',
|
|
size: 100,
|
|
required: false,
|
|
default: null,
|
|
array: false,
|
|
encrypt: false
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(nameAttributeResponse, 'name attribute created successfully', (r) => r.status === 202);
|
|
|
|
// Create age attribute
|
|
const ageAttributeResponse = http.post(
|
|
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/integer`,
|
|
JSON.stringify({
|
|
key: 'age',
|
|
required: false,
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(ageAttributeResponse, 'age attribute created successfully', (r) => r.status === 202);
|
|
|
|
// Create email attribute
|
|
const emailAttributeResponse = http.post(
|
|
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/email`,
|
|
JSON.stringify({
|
|
key: 'email',
|
|
required: false,
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(emailAttributeResponse, 'email attribute created successfully', (r) => r.status === 202);
|
|
|
|
// Create height attribute
|
|
const heightAttributeResponse = http.post(
|
|
`${endpoint}/databases/${databaseId}/collections/${collectionId}/attributes/float`,
|
|
JSON.stringify({
|
|
key: 'height',
|
|
required: false,
|
|
}),
|
|
{ headers: apiHeaders }
|
|
);
|
|
|
|
assert(heightAttributeResponse, 'height attribute created successfully', (r) => r.status === 202);
|
|
|
|
return {
|
|
databaseId,
|
|
collectionId
|
|
};
|
|
}
|
|
|
|
export function cleanup(config) {
|
|
const {
|
|
endpoint,
|
|
teamId,
|
|
headers
|
|
} = config;
|
|
|
|
// Delete Organization
|
|
const organizationResponse = http.del(
|
|
`${endpoint}/teams/${teamId}`,
|
|
null,
|
|
{
|
|
headers
|
|
}
|
|
);
|
|
|
|
assert(organizationResponse, 'organization deleted successfully', (r) => r.status === 204);
|
|
}
|
|
|
|
export function unique() {
|
|
const timestamp = Date.now().toString(36);
|
|
const randomPart = Math.random().toString(36).substring(2, 15);
|
|
return `${timestamp}-${randomPart}`;
|
|
} |