362 lines
12 KiB
JavaScript
362 lines
12 KiB
JavaScript
import { Client, Databases, Teams, Users, ID, Permission, Role, Query } from 'node-appwrite';
|
|
import { readFileSync } from 'fs';
|
|
import { resolve, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
function loadEnv() {
|
|
const envPath = resolve(__dirname, '..', '.env');
|
|
const lines = readFileSync(envPath, 'utf-8').split('\n');
|
|
for (const line of lines) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
const eqIdx = trimmed.indexOf('=');
|
|
if (eqIdx === -1) continue;
|
|
const key = trimmed.slice(0, eqIdx).trim();
|
|
const value = trimmed.slice(eqIdx + 1).trim();
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
|
|
loadEnv();
|
|
|
|
const ENDPOINT = process.env.APPWRITE_ENDPOINT;
|
|
const PROJECT_ID = process.env.VITE_APPWRITE_PROJECT_ID;
|
|
const API_KEY = process.env.APPWRITE_API_KEY;
|
|
const DATABASE_ID = process.env.VITE_APPWRITE_DATABASE_ID || 'defekttrack_db';
|
|
|
|
if (!ENDPOINT || !PROJECT_ID || !API_KEY || API_KEY === 'YOUR_API_KEY_HERE') {
|
|
console.error('Bitte APPWRITE_ENDPOINT, VITE_APPWRITE_PROJECT_ID und APPWRITE_API_KEY in .env setzen.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const client = new Client()
|
|
.setEndpoint(ENDPOINT)
|
|
.setProject(PROJECT_ID)
|
|
.setKey(API_KEY);
|
|
|
|
const databases = new Databases(client);
|
|
const teamsService = new Teams(client);
|
|
const users = new Users(client);
|
|
|
|
const TEAM_ROLES = ['admin', 'firmenleiter', 'filialleiter', 'service', 'lager'];
|
|
|
|
async function createDatabase() {
|
|
try {
|
|
const db = await databases.create(DATABASE_ID, 'DefektTrack DB');
|
|
console.log(`Datenbank erstellt: ${db.$id}`);
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log(`Datenbank existiert bereits: ${DATABASE_ID}`);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function createLocationsCollection() {
|
|
const COLLECTION_ID = 'locations';
|
|
try {
|
|
await databases.createCollection(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
'Standorte',
|
|
[
|
|
Permission.read(Role.users()),
|
|
Permission.create(Role.team('admin')),
|
|
Permission.update(Role.team('admin')),
|
|
Permission.delete(Role.team('admin')),
|
|
]
|
|
);
|
|
console.log('Collection erstellt: locations');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log('Collection existiert bereits: locations');
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'name', 128, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'address', 256, false, '');
|
|
await databases.createBooleanAttribute(DATABASE_ID, COLLECTION_ID, 'isActive', false, true);
|
|
console.log(' Attribute fuer locations erstellt (name, address, isActive)');
|
|
}
|
|
|
|
async function createUsersMetaCollection() {
|
|
const COLLECTION_ID = 'users_meta';
|
|
try {
|
|
await databases.createCollection(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
'Benutzer-Metadaten',
|
|
[
|
|
Permission.read(Role.users()),
|
|
Permission.create(Role.team('admin')),
|
|
Permission.update(Role.users()),
|
|
Permission.delete(Role.team('admin')),
|
|
]
|
|
);
|
|
console.log('Collection erstellt: users_meta');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log('Collection existiert bereits: users_meta');
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'userId', 64, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'locationId', 64, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'userName', 128, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'role', 32, true);
|
|
await databases.createBooleanAttribute(DATABASE_ID, COLLECTION_ID, 'mustChangePassword', false, true);
|
|
console.log(' Attribute fuer users_meta erstellt (userId, locationId, userName, role, mustChangePassword)');
|
|
}
|
|
|
|
async function createLagerstandorteCollection() {
|
|
const COLLECTION_ID = 'lagerstandorte';
|
|
try {
|
|
await databases.createCollection(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
'Lagerstandorte',
|
|
[
|
|
Permission.read(Role.users()),
|
|
Permission.create(Role.team('admin')),
|
|
Permission.update(Role.team('admin')),
|
|
Permission.delete(Role.team('admin')),
|
|
Permission.create(Role.team('filialleiter')),
|
|
Permission.update(Role.team('filialleiter')),
|
|
Permission.delete(Role.team('filialleiter')),
|
|
]
|
|
);
|
|
console.log('Collection erstellt: lagerstandorte');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log('Collection existiert bereits: lagerstandorte');
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'name', 128, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'locationId', 64, true);
|
|
await databases.createBooleanAttribute(DATABASE_ID, COLLECTION_ID, 'isActive', false, true);
|
|
console.log(' Attribute fuer lagerstandorte erstellt (name, locationId, isActive)');
|
|
}
|
|
|
|
async function createAssetsCollection() {
|
|
const COLLECTION_ID = 'assets';
|
|
try {
|
|
await databases.createCollection(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
'Assets',
|
|
[
|
|
Permission.read(Role.users()),
|
|
Permission.create(Role.users()),
|
|
Permission.update(Role.users()),
|
|
Permission.delete(Role.team('admin')),
|
|
Permission.delete(Role.team('filialleiter')),
|
|
]
|
|
);
|
|
console.log('Collection erstellt: assets');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log('Collection existiert bereits: assets');
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'erlNummer', 64, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'seriennummer', 128, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'artikelNr', 64, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'bezeichnung', 256, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'defekt', 1024, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'lagerstandortId', 64, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'zustaendig', 128, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'status', 32, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'prio', 16, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'kommentar', 2048, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'createdBy', 128, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'lastEditedBy', 128, false, '');
|
|
console.log(' Attribute fuer assets erstellt (erlNummer, seriennummer, artikelNr, bezeichnung, defekt, lagerstandortId, zustaendig, status, prio, kommentar, createdBy, lastEditedBy)');
|
|
}
|
|
|
|
async function createAuditLogsCollection() {
|
|
const COLLECTION_ID = 'audit_logs';
|
|
try {
|
|
await databases.createCollection(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
'Audit Logs',
|
|
[
|
|
Permission.read(Role.users()),
|
|
Permission.create(Role.users()),
|
|
]
|
|
);
|
|
console.log('Collection erstellt: audit_logs');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log('Collection existiert bereits: audit_logs');
|
|
return;
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'assetId', 64, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'action', 64, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'details', 2048, false, '');
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'userId', 64, true);
|
|
await databases.createStringAttribute(DATABASE_ID, COLLECTION_ID, 'userName', 128, true);
|
|
|
|
await new Promise((r) => setTimeout(r, 2000));
|
|
|
|
try {
|
|
await databases.createIndex(DATABASE_ID, COLLECTION_ID, 'idx_assetId', 'key', ['assetId'], ['ASC']);
|
|
console.log(' Index erstellt: idx_assetId');
|
|
} catch (err) {
|
|
if (err.code === 409) console.log(' Index existiert bereits: idx_assetId');
|
|
else throw err;
|
|
}
|
|
|
|
console.log(' Attribute fuer audit_logs erstellt (assetId, action, details, userId, userName)');
|
|
}
|
|
|
|
async function createTeams() {
|
|
for (const role of TEAM_ROLES) {
|
|
try {
|
|
await teamsService.create(role, role.charAt(0).toUpperCase() + role.slice(1));
|
|
console.log(`Team erstellt: ${role}`);
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log(`Team existiert bereits: ${role}`);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function createDefaultLocation() {
|
|
const existing = await databases.listDocuments(DATABASE_ID, 'locations', [Query.limit(1)]);
|
|
if (existing.documents.length > 0) {
|
|
console.log(`Filiale existiert bereits: "${existing.documents[0].name}"`);
|
|
return existing.documents[0].$id;
|
|
}
|
|
|
|
await new Promise((r) => setTimeout(r, 2000));
|
|
|
|
const loc = await databases.createDocument(DATABASE_ID, 'locations', ID.unique(), {
|
|
name: 'Hauptfiliale',
|
|
address: '',
|
|
isActive: true,
|
|
});
|
|
console.log(`Filiale erstellt: "Hauptfiliale" (${loc.$id})`);
|
|
return loc.$id;
|
|
}
|
|
|
|
async function createAdminUser(defaultLocationId) {
|
|
const ADMIN_EMAIL = 'admin@defekttrack.local';
|
|
const ADMIN_PASSWORD = 'Admin1234!';
|
|
const ADMIN_NAME = 'Administrator';
|
|
|
|
let userId;
|
|
try {
|
|
const user = await users.create(ID.unique(), ADMIN_EMAIL, undefined, ADMIN_PASSWORD, ADMIN_NAME);
|
|
userId = user.$id;
|
|
console.log(`Admin-User erstellt: ${ADMIN_EMAIL} (ID: ${userId})`);
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log(`Admin-User existiert bereits: ${ADMIN_EMAIL}`);
|
|
const userList = await users.list([Query.equal('email', [ADMIN_EMAIL])]);
|
|
if (userList.users.length > 0) {
|
|
userId = userList.users[0].$id;
|
|
} else {
|
|
console.log(' Konnte bestehenden Admin nicht finden, ueberspringe Team-Zuordnung.');
|
|
return;
|
|
}
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
try {
|
|
await teamsService.createMembership('admin', [], ADMIN_EMAIL, userId, undefined, `${ENDPOINT}/auth/confirm`);
|
|
console.log(' Admin dem Team "admin" hinzugefuegt');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log(' Admin ist bereits im Team "admin"');
|
|
} else {
|
|
console.warn(' Team-Membership Warnung:', err.message);
|
|
}
|
|
}
|
|
|
|
try {
|
|
await databases.createDocument(DATABASE_ID, 'users_meta', ID.unique(), {
|
|
userId,
|
|
locationId: defaultLocationId || '',
|
|
userName: ADMIN_NAME,
|
|
role: 'admin',
|
|
mustChangePassword: false,
|
|
});
|
|
console.log(' users_meta Dokument fuer Admin erstellt');
|
|
} catch (err) {
|
|
if (err.code === 409) {
|
|
console.log(' users_meta Dokument existiert bereits');
|
|
} else {
|
|
console.warn(' users_meta Warnung:', err.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log('=== DefektTrack Appwrite Setup ===');
|
|
console.log(`Endpoint: ${ENDPOINT}`);
|
|
console.log(`Projekt: ${PROJECT_ID}`);
|
|
console.log('');
|
|
|
|
await createDatabase();
|
|
console.log('');
|
|
|
|
await createLocationsCollection();
|
|
console.log('');
|
|
|
|
await createUsersMetaCollection();
|
|
console.log('');
|
|
|
|
await createLagerstandorteCollection();
|
|
console.log('');
|
|
|
|
await createAssetsCollection();
|
|
console.log('');
|
|
|
|
await createAuditLogsCollection();
|
|
console.log('');
|
|
|
|
await createTeams();
|
|
console.log('');
|
|
|
|
const defaultLocationId = await createDefaultLocation();
|
|
console.log('');
|
|
|
|
await createAdminUser(defaultLocationId);
|
|
console.log('');
|
|
|
|
console.log('=== Setup abgeschlossen ===');
|
|
console.log('');
|
|
console.log('Admin-Login:');
|
|
console.log(' E-Mail: admin@defekttrack.local');
|
|
console.log(' Passwort: Admin1234!');
|
|
console.log('');
|
|
console.log('Vergiss nicht, den API-Key aus .env zu entfernen oder sicher aufzubewahren.');
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Setup fehlgeschlagen:', err);
|
|
process.exit(1);
|
|
});
|