


Erstellen einer SaaS-Anwendung mit mehreren Mietern mit Next.js (Backend Integration)
Ich habe eine funktionale SaaS-Anwendung mit mehreren Mandanten (eine EdTech-App) mit Ihrem täglichen Tech-Tool erstellt und Sie können dasselbe tun.
Was ist eine SaaS-Anwendung mit mehreren Mietern?
Mit Multi-Tenant-SaaS-Anwendungen können Sie mehrere Kunden aus einer einzelnen Codebasis bedienen. Dazu müssen Sie jedoch einen sicheren und mieterspezifischen Zugang verwalten, und dies kann eine Herausforderung sein, wenn Sie manuell durchgeführt werden. Deshalb habe ich mich für die Nutzung der Genehmigung entschieden, ein modernes Autorisierungstool, das diesen Prozess vereinfacht.
In diesem Artikel zeige ich Ihnen, wie Sie die Autorisierung für Ihre SaaS-Anwendungen mithilfe der Genehmigung vereinfachen, mit einem Schritt-für-Schritt-Beispiel für den Aufbau einer Demo-App mit Mieter-Isolation und rollenbasiertem Zugriffskontroll (RBAC) mit Next.js und Appwrite.
Was sind als nächstes.js und Appwrite und warum brauchen wir sie?
Weiter.js
Next.js ist ein auf React-basiertes Framework, das Server-Side-Rendering (SSR), SSG (SSG), API-Routen und Leistungsoptimierungen für die statische Site ermöglicht.
Für dieses Projekt habe ich Next.js verwendet, weil:
- Es ermöglicht die Vorrenderung von Seiten, was die Leistung und die SEO verbessert.
- Das integrierte Routing erleichtert die Verwaltung von Seitenübergängen und dynamischen Inhalten.
- Es wird einfach in Backend -Dienste wie AppWrite und erzulassen.io zur Authentifizierung und Autorisierung integriert.
Appwrite
AppWrite ist eine BAAS-Plattform (Backend-As-a-Service), die Benutzerauthentifizierung, Datenbanken, Speicher und serverlose Funktionen bietet. Durch die Verwendung eines Dienstes wie AppWrite müssen Sie ein Backend von Grund auf erstellen, sodass Sie sich auf die Frontend -Entwicklung konzentrieren können und gleichzeitig Zugriff auf Backend -Funktionen haben.
Für dieses Projekt habe ich Appwrite verwendet:
- Um Benutzerregistrierung, Anmeldung und Sitzungsverwaltung zu behandeln.
- Bereitstellung einer strukturierten NOSQL-Datenbank zum Speichern von mieterspezifischen Daten.
Durch die Verwendung von Next.js und AppWrite zusammen ermöglichte ich eine skalierbare, leistungsstarke SaaS-App mit mehreren Mandanten und hält gleichzeitig den Entwicklungsprozess effizient.
Einführung in die Multi-Mieter-SaaS-Autorisierung
Eine SaaS-App mit mehreren Tenanten ist eine Software, die mehreren Benutzern oder Benutzergruppen dient, die als Mieter bezeichnet werden und eine einzige Softwareinstanz der Anwendung verwendet werden.
Es bedeutet, dass in einer SaaS-Architektur mit mehreren Mietern mehrere Kunden (Mieter) dieselbe Anwendungsinfrastruktur teilen oder dieselbe Anwendung verwenden, aber die Datenisolierung beibehalten.
Ein praktisches Beispiel dafür ist ein Projektmanagement -Tool wie Trello.
- Es handelt sich um eine einzige Infrastruktur, die auf gemeinsam genutzten Servern ausgeführt wird und die gleiche Codebasis für alle Benutzer enthält.
- Jedes Unternehmen, das Trello (z. B. Unternehmen A und Firma B) verwendet, ist ein Mieter.
- Es isoliert Daten:
- Mitarbeiter des Unternehmens A können ihre Projekte, Aufgaben und Vorstände nur sehen.
- Mitarbeiter des Unternehmens B können keine Daten von Unternehmen A zugreifen oder sie ansehen und umgekehrt.
Dies stellt sicher, dass die Daten und Aktivitäten jedes Mieters, während die Ressourcen geteilt werden, privat und sicher sind.
In einer Multi-Mieter-Anwendung haben einige Benutzer selbst innerhalb eines Mieters einen höheren Zugriff auf einige Informationen, während einige Mitglieder auf bestimmte Ressourcen beschränkt sind.
Genehmigung in solchen Bewerbungen muss:
- Stellen Sie sicher, dass Benutzer nicht auf Daten oder Ressourcen anderer Mieter oder Kunden zugreifen können. Dies nennt man isolierende Mieter.
- Stellen Sie sicher, dass Benutzer innerhalb eines Mieters nur auf Ressourcen zugreifen können, die ihre Rollen ermöglichen, indem sie eine detaillierte Zugriffskontrolle ermöglichen.
- Behandeln Sie mehr Benutzer, Mieter und Rollen, ohne die Leistung zu verlangsamen oder zu verschlechtern.
Bedeutung der Mieterisolation und der körnigen Zugangskontrolle
Die Isolation von Mietern hält die Daten sicher, indem sichergestellt wird, dass die Informationen jedes Kunden privat bleiben. Während die granulare Zugriffskontrolle sicherstellt, dass Benutzer innerhalb einer Organisation nur die Berechtigungen erhalten, die sie benötigen.
Die Implementierung der Autorisierung in Ihren SaaS -Apps kann komplex und schwierig sein, aber es muss nicht sein, wenn Sie über ein autorisierungsbedingtes Instrument wie Erlaubnis verfügen.
Was ist die Erlaubnis und wie hoch sind ihre Vorteile?
Die Genehmigung ist ein benutzerfreundliches Autorisierungs-Tool für die Verwaltung des Zugriffs in jeder Anwendung, einschließlich Multi-Mandanten-Apps. Mithilfe von generit.io in Ihrer Anwendung können Sie die Rollen in Ihrer Anwendung auf einfache Weise Rollen für die Zugriffskontrolle definieren und zuweisen. Neben dem Erstellen von Rollen innerhalb der Anwendung können Sie auch Bedingungen und Regeln auf der Grundlage von Benutzer- oder Ressourcenattributen hinzufügen, um anzugeben, was jeder Benutzer tun kann und was nicht.
Nachdem Sie nun das meiste wissen, was Sie über die Erlaubnis und ihre Vorteile wissen müssen, lassen Sie uns in das Hauptgeschäft eingehen.
Um die Leistung der Genehmigung zu demonstrieren, werden wir eine Multi-Mieter-EDTech SaaS-Plattform bauen.
Der Aufbau einer Edtech SaaS-Plattform beinhaltet mehrere Herausforderungen, darunter Benutzerauthentifizierung, rollenbasierte Access Control (RBAC) und Multi-Messen. Wir werden Next.js für das Frontend, Appwrite für Authentifizierung und Datenbankverwaltung und die Erlaubnis für die feinkörnige Genehmigung verwenden.
Tech -Stack -Übersicht
Systemarchitektur
Die Anwendung folgt einem Backend-First-Ansatz:
- Backend (Node.js Express)
- Behandelt API -Anfragen und Geschäftslogik.
- Verwendet AppWrite für Authentifizierung und Datenbankverwaltung.
- Implementierung der Erlaubnis zur Genehmigung, Definieren von Rollen und Berechtigungen.
- Stellen Sie sicher, dass jede Anfrage vor dem Datenzugriff validiert wird.
- Frontend (next.js)
- Stellt eine Verbindung zum Backend her, um Daten sicher abzurufen.
- Verwendet eine rollenbasierte UI-Rendering, was bedeutet, dass Benutzer nur sehen, auf was sie zugegriffen werden.
- Beschränken Sie Aktionen (z. B. Erstellen von Zuordnungen) basierend auf Berechtigungen.
Durch die Durchsetzung der Autorisierung auf API -Ebene stellen wir sicher, dass Benutzer keine Beschränkungen umgehen können, selbst wenn sie die Frontend manipulieren.
Am Ende dieses Handbuchs haben Sie eine voll funktionsfähige Multi-Tenant-Edtech SaaS-App, in der:
- Administratoren können Schüler hinzufügen und anzeigen.
- Lehrer können Schüler hinzufügen und anzeigen und Aufgaben erstellen.
- Die Schüler können ihre zugewiesenen Kursarbeit nur anzeigen.
Dieser Artikel enthält eine Schritt-für-Schritt-Aufschlüsselung darüber, wie ich die Genehmigung für die Erstellung dieses Projekts implementiert habe. Folgen und bauen Sie Ihre.
Backend -Implementierung mit Genehmigung
Um eine rollenbasierte Zugriffskontrolle (RBAC) und die Isolation von Mietern durchzusetzen, müssen wir:
- Richten und definieren Sie Rollen, Mieter und Richtlinien.
- Integrieren Sie die Erlaubnis in das Backend (Node.js Express).
- Schützen Sie API -Routen mithilfe von Middleware, die die Berechtigungen überprüft, bevor Anforderungen zuzulassen.
Lass uns Schritt für Schritt gehen.
1. Einrichten der Genehmigung
Vor dem Schreiben eines Codes müssen Sie
- Erstellen Sie ein Konto für die Genehmigung.

Sie erhalten das Onboarding, aber sobald Sie Ihren Organisationsnamen eingeben, können Sie einfach das Setup überspringen.
- Erstellen Sie eine Ressource und Aktionen
Navigieren Sie zum Richtlinienabschnitt, in dem Sie eine Ressource und Aktionen erstellen, die Sie in dieser Ressource ausführen können.

Sobald Sie mit dem Erstellen Ihrer Ressourcen fertig sind, sollte dies so aussehen:

- Eine Rolle schaffen
Navigieren Sie nach dem Erstellen der Ressourcen mit der Registerkarte Rollen zur Seite der Rollen. Sie werden sehen, dass einige Rollen automatisch zugewiesen wurden.

Löschen Sie diese Rollen und erstellen Sie neue Rollen. Jede Rolle ist mit spezifischen Regeln zugeordnet, was ein Benutzer kann und was nicht. Erstellen Sie zuerst die Administratorrolle, da sie später als Baustein für die RBAC -Bedingungen dienen wird. Klicken Sie oben auf die Schaltfläche Rollen hinzufügen und erstellen Sie die Rollen.

Wenn Sie mit dem Erstellen Ihrer Rollen fertig sind, sollte dies so aussehen:

Großartig!
Nachdem Sie Ihre Ressourcen und Rollen erstellt haben, können Sie jetzt Berechtigungen im Richtlinieneditor konfigurieren.
- Konfigurieren von Berechtigungen im Richtlinieneditor
Kehren Sie zum Richtlinieneditor zurück und so werden die Rollen jetzt aussehen, wobei jede einzelne Ressource definiert und die Aktionen, die Sie auswählen können. Sie sind jetzt bereit, den Rollen Berechtigungen zu erteilen, um die ausgewählten Aktionen auf der Ressource auszuführen.

Wenn Sie fertig sind, um die Aktionen für jede Rolle auszuwählen, klicken Sie unten rechts auf die Schaltfläche "Änderungen speichern".
- API -Schlüssel kopieren
Um den Cloud -PDP der Genehmigung zu verwenden, benötigen Sie den API -Schlüssel Ihrer aktuellen Umgebung. Für dieses Projekt werden Sie den Entwicklungsumfeldschlüssel verwenden. Fahren Sie mit den Einstellungen fort und klicken Sie auf API -Schlüssel, scrollen Sie nach unten zu Umgebungs -API -Schlüssel, klicken Sie auf "Taste" und kopieren Sie es.

Nachdem Sie Ihr Erlaubnis -Dashboard eingerichtet haben, können Sie jetzt zu Ihrem Backend übergehen.
2. Installieren von Abhängigkeiten
Um loszulegen, müssen Sie Node.js auf Ihrem Computer installieren lassen. Befolgen Sie die folgenden Schritte, nachdem sichergestellt wird, dass Node.js in Ihrem System installiert ist:
- Erstellen Sie mit den folgenden Befehlen ein neues Projekt:
Mkdir Backend CD -Backendnpm init -y
- Installieren Sie dann die folgenden Pakete:
NPM Installieren Sie Express dotenv generell cors Appwwrite axios jsonWeBtoken
- Konfigurieren Sie die Genehmigung in Express. Speichern Sie in Ihrer .EnV -Datei Ihre API -Taste:
Erlauben_api_key = your-permit-key-you-copied-earlier
3. Einrichten von Appwrite
- Gehen Sie zu AppWrite und erstellen Sie ein neues Projekt, indem Sie einen Projektnamen eingeben und eine Region auswählen. Beachten Sie Ihre Projekt -ID und API -Endpunkt. Das werden Sie als Werte in Ihrer .env -Datei eingeben. Ihre Env -Datei sollte so aussehen:
Erlauben_api_key = your-permit-key-you-copied-earlier Appwrite_endpoint = https: //cloud.appwrite.io/v1 Appwrite_project_id = your-project-id
- Fahren Sie nun zu Datenbanken fort, um Ihre Datenbank zu erstellen, und kopieren Sie Ihre Datenbank -ID, um sie in Ihre Env -Datei einzufügen.

Ihre Env -Datei sollte jetzt so aussehen:
Erlauben_api_key = your-permit-key-you-copied-earlier Appwrite_endpoint = https: //cloud.appwrite.io/v1 Appwrite_project_id = your-project-id Appwrite_database_id = your-database-id
Erstellen Sie nun die folgenden Sammlungen in der AppWrite -Datenbank mit den folgenden Attributen:
- Profilsammlung

- Studentensammlung

- Aufgaben Sammlung

Wie Ihre Env -Datei an diesem Punkt aussehen sollte:
Erlauben_api_key = your-permit-key-you-copied-earlier Erlauben_project_id = Copy-from-Dasboard Erlauben_env_id = Copy-from-Dasboard Appwrite_endpoint = https: //cloud.appwrite.io/v1 Appwrite_project_id = your-project-id Appwrite_database_id = your-database-id Appwrite_profile_collection_id = your-id Appwrite_asssignments_collection_id = your-id Appwrite_students_collection_id = your-id Jwt_secret = generate-this-by-running // openssl rand -base64 16 Port = 8080
4. Erstellen Sie Dateistruktur und Dateien
Erstellen Sie nun einen SRC -Ordner im Root der Datei. Generieren Sie dann die Datei tsconfig.json im Root -Ordner und fügen Sie den folgenden Code in sie ein:
<span>{ </span><span>"Compileroptions": {{ </span><span>"Ziel": "ES6", </span><span>"Modul": "Commonjs", </span><span>"Outdir": "./Dist", </span><span>"EsmoduleInterop": true, </span><span>"ForceconsistentcasinginfileNames": wahr, </span><span>"streng": wahr, </span><span>"SkipliBcheck": wahr, </span><span>"ResolvejsonModule": Richtig, </span><span>"BaseUrl": "./", </span><span>"Pfade": { </span><span>"@/*": ["src/*"] </span><span>} </span><span>}, </span><span>"Include": ["src/**/*"], </span><span>"ausschließen": ["node_modules", "dist"] </span><span>}</span>
Dieser tsconfig.json konfiguriert den TypeScript -Compiler, um ES6 zu zielen, CommonJS -Module zu verwenden und Dateien auf ./DIST auszugeben. Es erzwingt strenge Typ-Überprüfungen, ermöglicht die Auflösung des JSON-Moduls, legt Pfad-Aliase für SRC ein und schließt NODE_MODULES und DIST aus der Kompilierung aus.
Erstellen Sie im SRC -Ordner die folgenden Ordner: API, Konfiguration, Controller, Middleware, Modelle und Utils.
- Utils -Ordner
- Erstellen Sie nun eine neue Genehmigung.TS -Datei im Utils -Ordnerprojekt, um die Genehmigung mithilfe des folgenden Code zu initialisieren:
<span>import {genehmigen} aus 'illyio'; </span><span>Import {erlaubte_api_key} aus '../config/environment'; </span><span>// Diese Zeile initialisiert die SDK und verbindet Ihre Node.js -App </span><span>// In den PDP -Container von genannten.io, den Sie im vorherigen Schritt eingerichtet haben. </span><span>const erlaubte = neue Erlaubnis ({{{ </span><span>// Ihre API -Schlüssel </span> Token <span>: Erlaubnis_API_KEY, // Speichern Sie Ihren API -Schlüssel in .Env </span><span>// In der Produktion müssen Sie möglicherweise diese URL ändern, um Ihre Bereitstellung zu entsprechen </span> PDP <span>: 'https://cloudpdp.api.permit.io', // Standard -Genehmigung.io PDP -URL </span><span>// Wenn Sie möchten, dass der SDK Protokolle abgibt, wenden Sie sich an: </span> Protokoll <span>: { </span> Level <span>: "Debugg", </span><span>}, </span><span>// Der SDK gibt false zurück, wenn Sie einen Timeout- / Netzwerkfehler erhalten </span><span>// Wenn Sie möchten, dass es stattdessen einen Fehler macht, und Sie damit umgehen lassen, wenden Sie sich an: </span><span>// thryonError: wahr, </span><span>}); </span> <span>Ausfuhrverzugserlaubnis;</span>
Diese Datei initialisiert das SDK von Gen Dient für node.js und verbindet sie mit dem PDP -Container der Genehmigung mit einem in der Umgebung gespeicherten API -Schlüssel. Es konfiguriert die Protokollierung für das Debuggen und richtet die SDK so ein, dass Fehler lautlos verarbeitet werden, sofern sie nicht explizit konfiguriert werden, um sie zu werfen.
- Erstellen Sie anschließend eine Datei namens ERRAGEHANDLER.TS und fügen Sie den folgenden Code ein:
<span>// Versorgungsfunktionen (z. B. Fehlerbehandlung) </span><span>importieren {request, antwort, nextFunction} aus 'Express'; </span> <span>exportieren const erfehlerhandler = (ERR: Any, Req: Request, Res: Antwort, Weiter: NextFunction) => { </span><span>console.Error ('error:', err.message || err); </span> res <span>.status (err.status || 500) .json ({{{{ </span> Fehler <span>: err.message || 'Interner Serverfehler', </span><span>}); </span><span>};</span>
Diese Datei definiert eine Express-Fehlerhandling-Middleware, die Fehler protokolliert und eine JSON-Antwort mit der Fehlermeldung und dem Statuscode sendet. Es wird standardmäßig mit einem 500 -Status -Code eingestuft, wenn kein spezifischer Status bereitgestellt wird.
- Modelle Ordner
- Erstellen Sie eine Datei namens Profil.TS und fügen Sie den folgenden Code ein:
<span>Export -Schnittstellenprofil exportieren { </span> Name <span>: String; </span> E -Mail <span>: Zeichenfolge; </span> Rolle <span>: 'Admin' | 'Lehrer' | 'Student'; </span> BenutzerID <span>: String; </span><span>}</span>
Diese Datei definiert eine TypeScript -Profil -Schnittstelle mit Eigenschaften für Name, E -Mail, Rolle und BenutzerID, wobei die Rolle auf bestimmte Werte beschränkt ist: Administrator, Lehrer oder Schüler.
- Datei zuweisen.ts Datei erstellen und fügen Sie den folgenden Code ein:
<span>{Datenbank importieren, id} aus '../config/appwrite'; </span><span>Import {database_id, teliMents_collection_id} aus '../config/environment'; </span> <span>Exportieren der Schnittstellenzuweisungen exportieren { </span> Titel <span>: String; </span> Betreff <span>: String; </span> Klassenname <span>: String; </span> Lehrer <span>: String; </span> duedate <span>: String; </span> Creatoremail <span>: String; </span><span>} </span> <span>// Erstellen Sie eine neue Zuordnung </span><span>Exportieren Sie die asynchronisierte Funktion createasSsignmentIndB (Daten: ordnungsdata) { </span><span>Warten Sie warten auf database.createdocument ( </span><span>Datenbank_id, </span><span>Zuweisungen_Collection_id, </span><span>Id.unique (), </span> Daten <span>); </span><span>} </span> <span>// Alle Aufgaben abrufen </span><span>exportieren </span><span>const response = warte auf database.listdocuments (Database_id, telegments_collection_id); </span><span>Rückgabeantwort.Dokumente; </span><span>}</span>
Diese Datei bietet Funktionen für die Interaktion mit einer AppWrite -Datenbank zum Verwalten von Zuordnungen. Es definiert eine Zuweisungs -Schnittstelle und enthält Funktionen zum Erstellen einer neuen Zuordnung und zum Abholen aller Zuordnungen aus der Datenbank.
- Erstellen Sie eine student.ts -Datei und fügen Sie den folgenden Code ein:
<span>Import {Datenbank, ID, Erlaubnis, Rolle, Abfrage} aus '../config/appwrite'; </span><span>import {database_id, student_collection_id} aus '../config/environment'; </span> <span>Export -Schnittstelle studentData { </span> FirstName <span>: String; </span> LastName <span>: String; </span> Geschlecht <span>: 'Mädchen' | 'Junge' | 'Junge' | 'Mädchen'; </span> Klassenname <span>: String; </span> Alter <span>: Zahl; </span> Creatoremail <span>: String; </span><span>} </span> <span>// Erstellen Sie einen neuen Schüler </span><span>Exportieren Sie die asynchronisierende Funktion CreatestudentIndb (Daten: StudentData) { </span><span>Warten Sie warten auf database.createdocument ( </span><span>Datenbank_id, </span><span>Students_collection_id, </span><span>Id.unique (), </span> Daten <span>, </span><span>[ </span> Erlaubnis <span>. </span><span>] </span><span>); </span><span>} </span> <span>// Alle Schüler holen </span><span>exportieren </span><span>const response = warte auf database.listdocuments (Database_id, student_collection_id); </span><span>Rückgabeantwort.Dokumente; </span><span>}</span>
Diese Datei bietet Funktionen zum Verwalten von Studentendaten in einer AppWrite -Datenbank. Es definiert eine StudentData -Schnittstelle und enthält Funktionen, um einen neuen Schüler mit öffentlichen Lesemerkenntnissen zu erstellen und alle Schüler aus der Datenbank zu holen.
- Middleware -Ordner
- Erstellen Sie die Datei auth.ts und fügen Sie den folgenden Code ein:
<span>importieren {request, antwort, nextFunction} aus 'Express'; </span><span>JWT von 'JsonWebtoken' importieren; </span> <span>// Anforderungsart so erweitern, um "Benutzer" einzuschließen. </span><span>Interface AuthenticatedRequest erweitert die Anfrage { </span> Benutzer <span>?: { </span> ID <span>: String; </span> Rolle <span>: String; </span><span>}; </span><span>} </span> <span>const authmiddleware = (req: authenticatedRequest, Res: Antwort, Weiter: NextFunction): void => { </span><span>const token = req.Headers.authorization? .Split ('') [1]; </span> <span>if (! token) { </span> res <span>.Status (401) .json ({Fehler: 'Unauthorized. No Token bereitgestellt'}); </span><span>zurückkehren </span><span>} </span> <span>versuchen { </span><span>const decoded = jwt.verify (token, process.env.jwt_secret!) AS {id: String; Rolle: String}; </span> req <span>.User = decodiert; </span><span>nächste(); </span><span>} catch (error) { </span> res <span>.Status (403) .json ({Fehler: 'Ungültiges Token'}); </span><span>zurückkehren </span><span>} </span><span>}; </span> <span>StandardauthMiddleware exportieren;</span>
Diese Datei definiert eine Express Middleware für JWT-basierte Authentifizierung. Es prüft ein gültiges Token im Anforderungsheader, überprüft es mithilfe eines geheimen Schlüssels und fügt die dekodierten Benutzerinformationen (ID und Rolle) an das Anforderungsobjekt an. Wenn das Token fehlt oder ungültig ist, gibt es eine geeignete Fehlerantwort zurück.
- Erstellen Sie Erlaubnis. Und fügen Sie den folgenden Code ein:
<span>Import -Genehmigung von '../utils/permit'; </span> <span>exportieren const CheckUsertopmitstudents = async (E -Mail: String, Aktion: String, Ressource: String): Versprechen <boolean> => { </boolean></span><span>versuchen { </span><span>const erlaubte = wartete genehmigen. Check (E -Mail, Aktion, Ressource); </span><span>console.log ("erlaubt", erlaubt); </span><span>Rückgabe erlaubt; </span><span>} catch (error) { </span><span>console.Error ( <span>`Fehlersynchronisierung von Benutzer <span>$ {E -Mail},</span> um zu erlauben.io:`</span> , Fehler); </span><span>false zurückgeben; </span><span>} </span><span>}; </span> <span>Export const const CheckUsertoperMitSignment = Async (E -Mail: String, Aktion: String, Ressource: String): Versprechen <boolean> => { </boolean></span><span>versuchen { </span><span>const erlaubte = wartete genehmigen. Check (E -Mail, Aktion, Ressource); </span><span>console.log ("erlaubt", erlaubt); </span><span>Rückgabe erlaubt; </span><span>} catch (error) { </span><span>console.Error ( <span>`Fehlersynchronisierung von Benutzer <span>$ {E -Mail},</span> um zu erlauben.io:`</span> , Fehler); </span><span>false zurückgeben; </span><span>} </span><span>};</span>
Diese Datei definiert Dienstprogrammfunktionen, CheckUsertopmitstudentents und CheckUsertoperMitSsignment, um die Erlaubnis der Benutzerberechtigungen für bestimmte Maßnahmen und Ressourcen zu überprüfen. Beide Funktionen verarbeiten Fehler anmutig, protokollieren Probleme und geben falsch zurück, wenn die Berechtigungsprüfung fehlschlägt. Sie werden verwendet, um die Genehmigung im Antrag durchzusetzen.
- Controller -Ordner
- Erstellen Sie die Datei auth.ts und fügen Sie den folgenden Code ein:
<span>{Konto importieren, id} aus '../config/appwrite'; </span><span>{Anfrage, Antwort} aus 'Express' importieren; </span><span>JWT von 'JsonWebtoken' importieren; </span> <span>const jwt_secret = process.env.jwt_secret as String; // Stellen Sie sicher, dass dies in Ihrer .env -Datei festgelegt ist </span> <span>// Anmeldesteuerung </span><span>Export const Signup = async (Req: Anfrage, Res: Antwort) => { </span><span>const {E -Mail, Passwort, Name} = req.body; </span> <span>if (! E -Mail ||! Passwort ||! Name) { </span><span>return res.status (400) .json ({Fehler: 'Name, E -Mail und Passwort sind erforderlich.'}); </span><span>} </span> <span>versuchen { </span><span>const user = act act account.create (id.unique (), mail, password, name); </span><span>// JWT erzeugen </span><span>const token = jwt.Sign ({E -Mail}, jwt_secret, {expiresin: '8H'}); </span> Res <span>.cookie ('Token', Token, { </span> httponly <span>: wahr, </span> samesit <span>: 'streng', </span> sicher <span>: wahr, </span><span>}); </span> Res <span>.Status (201) .json ({Erfolg: True, Benutzer, Token}); </span><span>} catch (Fehler: Any) { </span><span>console.Error ('Anmeldefehler:', Fehler); </span> res <span>.Status (500) .json ({Erfolg: false, meldung: error.message}); </span><span>} </span><span>}; </span> <span>// Login -Controller </span><span>Export const login = async (req: request, res: response) => { </span><span>const {E -Mail, Passwort} = req.body; </span> <span>if (! E -Mail ||! Passwort) { </span><span>return res.status (400) .json ({Fehler: 'E -Mail und Passwort sind erforderlich.'}); </span><span>} </span> <span>versuchen { </span><span>const session = act act account.createEmailpasswordSession (E -Mail, Passwort); </span> <span>// JWT ohne Rolle erzeugen </span><span>const token = jwt.sign ( </span><span>{userId: seseerid, E -Mail}, // keine Rolle enthalten </span><span>Jwt_secret, </span><span>{abgelaufen: '8H'} </span><span>); </span> Res <span>.cookie ('Token', Token, { </span> httponly <span>: wahr, </span> samesit <span>: 'streng', </span> sicher <span>: wahr, </span><span>}); </span> Res <span>.Status (200) .json ({Erfolg: true, token, session}); </span><span>} catch (Fehler: Any) { </span><span>console.Error ('Anmeldefehler:', Fehler); </span> res <span>.Status (401) .json ({Erfolg: false, meldung: error.message}); </span><span>} </span><span>}; </span> <span>// Logout -Controller </span><span>exportieren const logout = async (req: request, res: response) => { </span><span>versuchen { </span><span>Warte Account.Deletesession ('aktuelle Sitzungs -ID'); </span> res <span>.clearcookie ('token'); </span> Res <span>.Status (200) .json ({Erfolg: true, message: 'erfolgreich angemeldet'}); </span><span>} catch (Fehler: Any) { </span><span>console.Error ('logout error:', error); </span> res <span>.Status (500) .json ({Erfolg: false, meldung: error.message}); </span><span>} </span><span>};</span>
Diese Datei definiert Authentifizierungscontroller für Anmeldung, Anmeldung und Anmeldung und integriert sich in AppWrite für die Benutzerverwaltung und JWT für die Sitzung. Die Anmeldungs- und Anmeldecontroller validieren Eingaben, erstellen Benutzersitzungen und generieren JWTs, während der Abmeldesteuerungs -Controller die Sitzung und das Token löscht. Alle Controller verarbeiten Fehler und geben entsprechende Antworten zurück.
- Datei zuweisen.ts Datei erstellen und fügen Sie den folgenden Code ein:
<span>{Anfrage, Antwort} aus 'Express' importieren; </span><span>Import {CreateasSignmentIndB, ordnungsdata, fetchaDassignments aus} aus '../models/assignent'; </span><span>Import {CheckUsertopmitAssignment} aus '../middleware/permit'; </span> <span>// Erstellen Sie eine neue Zuordnung </span><span>Exportieren Sie die Asynchronisierungsfunktion CreateasSsignment (Requal: Request , Res: Antwort): Promise <void> { </void></span><span>versuchen { </span><span>const {title, Thema, Lehrer, Klassenname, duedate, CreateMail}: Auftragsdata = req.body; </span> <span>const isspermonded = Warte ucuSertopmitSsignment (CreateMail, "Create", "Zuweisungen"); </span><span>if (! isspermitted) { </span> res <span>.Status (403) .json ({Fehler: 'nicht autorisiert'}); </span><span>zurückkehren; </span><span>} </span> <span>const newAssignment = Warten Sie CreateasSignmentIndB ({{{{{{{{ </span> Titel <span>, </span> Thema <span>, </span> Lehrer, Lehrer <span>, </span> Klassenname <span>, </span> Fälligkeitsdatum <span>, </span> Creatoremail <span>}); </span> <span>console.log ('Neue Zuordnung erstellt:', NewSsignment); </span> Res <span>.Status (201) .Json (NewSsignment); </span><span>} catch (error) { </span><span>console.Error ('Erstellen von Fehlererstellung:', Fehler); </span> res <span>.Status (500) .json ({Fehler: (Fehler wie alle) .Message}); </span><span>} </span><span>} </span> <span>// Alle Aufgaben abrufen </span><span>Exportieren Sie Async -Funktionen FetchaSsignments (Req: Request, Res: Antwort): Versprechen <void> { </void></span><span>versuchen { </span><span>const {E -Mail} = req.params; </span> <span>const isspermitted = Warten Sie ucuSertopmitSsignment (E -Mail, "Read", "Aufgaben"); </span><span>if (! isspermitted) { </span> res <span>.Status (403) .json ({message: 'nicht autorisiert'}); </span><span>zurückkehren; </span><span>} </span> <span>const ordnungsgeräte = wartet fetchaDaNments aussomdb (); </span> Res <span>.Status (200) .Json (Zuweisungen); </span><span>} catch (error) { </span> res <span>.Status (500) .json ({Fehler: (Fehler wie alle) .Message}); </span><span>} </span><span>}</span>
Diese Datei definiert Controller für das Erstellen und Abholen von Zuweisungen, um sie in eine Datenbank zu integrieren und für Autorisierungsüberprüfungen zuzulassen. Der CreateasSsignment -Controller bestätigt Eingaben, überprüft die Berechtigungen und erstellt eine neue Zuordnung, während der FetchaDaD -Signment -Controller alle Zuordnungen nach Überprüfung des Zugriffs abruft. Beide Controller verarbeiten Fehler und geben entsprechende Antworten zurück.
- Erstellen Sie eine student.ts -Datei und fügen Sie den folgenden Code ein:
<span>importieren { </span> CreatestudentIndb <span>, </span> Fetchstudents <span>aus </span> Studentdata <span>} aus '../models/student'; </span><span>{Anfrage, Antwort} aus 'Express' importieren; </span><span>importieren {CheckUsertopmitstudents} aus '../middleware/permit'; </span> <span>Exportieren Sie die asynchronisierende Funktion des Kreaturs (Req: Request, Res: Antwort): Versprechen <void> { </void></span><span>versuchen { </span><span>const {FirstName, Nachname, Geschlecht, Klassenname, Alter, CreateMail}: StudentData = req.body; </span> <span>if (! ['Mädchen', 'Junge']. Enthält (Geschlecht)) { </span> res <span>.Status (400) .json ({Fehler: 'Ungültiger Geschlechtstyp'}); </span><span>zurückkehren; </span><span>} </span> <span>const isspermitted = Warten Sie ucuSertopmitstudents (CreateMail, "erstellen", "Schüler"); </span><span>if (! isspermitted) { </span> res <span>.Status (403) .json ({message: 'nicht autorisiert'}); </span><span>zurückkehren; </span><span>} </span> <span>const newstudent = warte CreateStudentIndB ({{ </span> FirstName <span>, </span> Lastname <span>, </span> Geschlecht <span>, </span> Klassenname <span>, </span> Alter <span>, </span> Creatoremail <span>}); </span> Res <span>.Status (201) .Json (NewStudent); </span><span>} catch (error) { </span> res <span>.Status (500) .json ({Fehler: (Fehler wie alle) .Message}); </span><span>} </span><span>} </span> <span>// Alle Schüler holen </span><span>Fetchstudents der asynchronischen Funktion exportieren (Requal: Request, Res: Antwort): Versprechen <void> { </void></span><span>versuchen { </span><span>const {E -Mail} = req.params; </span> <span>const isSermiteded = Warten Sie ucuSertopmitstudents (E -Mail, "lesen", "Studenten"); </span><span>if (! isspermitted) { </span> res <span>.Status (403) .json ({message: 'nicht autorisiert'}); </span><span>zurückkehren; </span><span>} </span> <span>const students = wartet fetchstudents fromdb (); </span> Res <span>.Status (200) .Json (Studenten); </span><span>} catch (error) { </span> res <span>.Status (500) .json ({Fehler: (Fehler wie alle) .Message}); </span><span>} </span><span>}</span>
Diese Datei definiert Controller für das Erstellen und Abholen von Schülern, die Integration in eine Datenbank und die Erlaubnis für Autorisierungsüberprüfungen. Der Createstudent Controller validiert Eingabe, überprüft die Berechtigungen und erstellt einen neuen Schüler, während der Fetchstudentents Controller alle Schüler nach Überprüfung des Zugriffs abruft. Beide Controller verarbeiten Fehler und geben entsprechende Antworten zurück.
- Erstellen Sie ein Profil.ts -Datei und fügen Sie den folgenden Code ein:
<span>{Profil} aus '@/models/profil' importieren; </span><span>Axios aus 'Axios' importieren; </span><span>Importieren {Datenbank, ID, Abfrage} aus '../config/appwrite'; </span><span>{Anfrage, Antwort, NextFunction, RequestHandler} aus 'Express'; </span><span>Import {erlaubte_api_key} aus '../config/environment'; </span> <span>const profileId = process.env.appwrite_profile_collection_id als String; // Stellen Sie sicher, dass dies in .Env ist </span><span>const DataBaseId = process.env.appwrite_database_id als String; // Stellen Sie sicher, dass dies in .Env ist </span><span>const projectId = process.env.permit_project_id als String </span><span>const EnvironmentID = process.env.permit_env_id als String </span> <span>const genehmigen_api_url = <span>`https://api.permit.io/v2/facts/ <span>$ {projectId}</span> / <span>$ {umweltid}</span> /user`</span> ; </span><span>const erlaubte_auth_Header = { </span> Autorisierung <span>: <span>`Bearer <span>$ {erlauben_api_key}</span> `</span> ,, </span><span>"Inhaltstyp": "Anwendung/JSON", </span><span>}; </span> <span>// Profilcontroller erstellen </span><span>Export const createProfile: RequestHandler = async (Req: Request, Res: Antwort, Weiter: Weitere Funktion): Versprechen <void> => { </void></span><span>const {FirstName, Nachname, E -Mail, Rolle, userID} = req.body; </span><span>console.log (req.body); </span> <span>if (! E -Mail ||! Rolle ||! UserId) { </span> res <span>.Status (400) .json ({Fehler: 'FirstName, LastName, E -Mail, Rolle und UserID sind erforderlich.'}); </span><span>zurückkehren; </span><span>} </span> <span>// Rolle validieren </span><span>const erlaubte: profile ['rolle'] [] = ['admin', 'lehrer', 'schüler']; </span><span>if (! erlaubtenroles.includes (Rolle)) { </span> res <span>.Status (400) .json ({Fehler: 'Ungültige Rolle. Erlaubte Rollen: admin, Lehrer, Schüler'}); </span><span>zurückkehren; </span><span>} </span> <span>versuchen { </span><span>const newuser = wartet database.createdocument ( </span> DatabaseId <span>, </span> ProfileId <span>, </span><span>Id.unique (), </span><span>{FirstName, LastName, E -Mail, Rolle, UserID} </span><span>); </span><span>// Schritt 2: Benutzer synchronisieren zu erlauben.io </span><span>const essPayload = { </span> Schlüssel <span>: E -Mail, </span> E -Mail, E -Mail <span>, </span> First_Name <span>: FirstName, </span> Last_name <span>: LastName, </span> ROLE_Ssignments <span>: [{Rolle, Mieter: "Standard"}], </span><span>}; </span> <span>Lassen Sie die Erlaubnis; </span><span>versuchen { </span><span>const response = warte axios.post (erlaubte_api_url, generellload, {headers: erlauben_auth_header}); </span> GenehmigungSResponse <span>= Antwort.Data; </span><span>console.log ("Benutzer synchronisiert zu genehmigen.io:", detialResponse); </span><span>} catch (erlaubterror) { </span><span>if (axios.isaxiOseseserror (erlaubterror)) { </span><span>console.Error ("nicht zu synchronisieren user to erlaubt.io:", erlaubterror.response?. </span><span>} anders { </span><span>console.Error ("Nicht synchronisieren, um zu erlauben. </span><span>} </span> detliclesponse <span>= {error: "versäschte es nicht, mit erlaubten.io"} zu synchronisieren; </span><span>} </span> <span>// Schritt 3: Beide Antworten zurückgeben </span> res <span>.status (201) .json ({{ </span> Nachricht <span>: "Benutzerprofil erfolgreich erstellt", </span> Benutzer <span>: Newuser, </span> Genehmigung <span>: Genehmigungsponse, </span><span>}); </span><span>zurückkehren; </span><span>} catch (Fehler: Any) { </span> res <span>.Status (500) .json ({Erfolg: false, meldung: error.message}); </span><span>zurückkehren; </span><span>} </span><span>}; </span> <span>// Profil per E -Mail abrufen </span><span>Export const GetProfileByemail = Async (Req: Request, Res: Antwort, Weiter: Weitere Funktion): Versprechen <void> => { </void></span><span>const {E -Mail} = req.params; </span> <span>if (! E -Mail) { </span> res <span>.Status (400) .json ({Fehler: 'E -Mail ist erforderlich.'}); </span><span>zurückkehren; </span><span>} </span> <span>versuchen { </span><span>const profile = wartet database.listdocuments ( </span> DatabaseId <span>, </span> ProfileId <span>, </span><span>[Query.equal ("E -Mail", E -Mail)]] </span><span>); </span> <span>if (profil.documents.length === 0) { </span> res <span>.Status (404) .json ({Fehler: 'Profil nicht gefunden'}); </span><span>zurückkehren; </span><span>} </span> Res <span>.Status (200) .json ({Erfolg: true, profil: profil.dokumente [0]}); </span><span>} catch (Fehler: Any) { </span><span>console.Error ('Fehler beim Abrufen von Fetching:', Fehler); </span> res <span>.Status (500) .json ({Erfolg: false, meldung: error.message}); </span><span>} </span><span>};</span>
Diese Datei definiert Controller zum Erstellen und Abholen von Benutzerprofilen, in der Integration in AppWrite für Datenbankvorgänge und ermöglichen die Rollensynchronisation. Der CreateProFile -Controller validiert Eingaben, erstellt ein Profil und synchronisiert den Benutzer, während der GetProfileByemail -Controller ein Profil per E -Mail abruft. Beide Controller verarbeiten Fehler und geben entsprechende Antworten zurück.
- Konfigurationsordner
- Erstellen Sie Appwrite.ts Datei und fügen Sie den folgenden Code ein:
<span>Importieren {Client, Konto, Datenbanken, Speicher, ID, Berechtigung, Rolle, Abfrage} aus 'AppWrite'; </span><span>Import {Appwrite_endpoint, Appwrite_project_id, Appwrite_API_Key} aus './environment'; </span> <span>// Initialisieren Sie den Appwrite -Client </span><span>const client = neuer client () </span><span>.setendpoint (Appwrite_endpoint) // Appwrite Endpoint </span><span>.setProject (appwrite_project_id); // Appwrite Project ID </span> <span>// API-Schlüssel hinzufügen, falls verfügbar (für serverseitige Operationen) </span><span>if (appwrite_api_key) { </span><span>(Client wie alle) .Config.Key = Appwrite_API_Key; // Problemumgehung, um den API -Schlüssel festzulegen </span><span>} </span> <span>// Appwrite -Dienste initialisieren </span><span>const Account = neues Konto (Client); </span><span>const Database = neue Datenbanken (Client); </span><span>const speicher = neuer Speicher (Client); </span> <span>// Appwrite -Client und -Dienste exportieren </span><span>exportieren {client, Konto, Datenbank, Speicher, ID, Erlaubnis, Rolle, Abfrage};</span>
Diese Datei initialisiert und konfiguriert den AppWrite -Client mit dem Projektendpunkt, der ID und des optionalen API -Schlüssels. Außerdem werden AppWrite -Dienste wie Konto, Datenbanken und Speicher zusammen mit Dienstprogrammkonstanten wie ID, Erlaubnis, Rolle und Abfrage eingerichtet und exportiert.
- Datei erstellen und fügen Sie den folgenden Code ein:
<span>dotenv aus 'dotenv' importieren; </span>dotenv <span>.config (); // Umgebungsvariablen von .env laden Umgebungsvariablen </span> <span>Export const Appwrite_endpoint = process.env.appwrite_endpoint || ''; </span><span>exportieren const erzulassen_api_key = process.env.permit_api_key || ''; </span><span>exportieren const genehmigen_project_id = process.env.permit_project_id || ''; </span><span>Export const erzulassen_env_id = process.env.permit_env_id || ''; </span><span>exportieren const Appwrite_project_id = process.env.appwrite_project_id || ''; </span><span>exportieren const database_id = process.env.appwrite_database_id || ''; </span><span>Export const students_collection_id = process.env.appwrite_students_collection_id || ''; </span><span>exportieren const zuweisungen_collection_id = process.env.appwrite_asssignments_collection_id || ''; </span> <span>exportieren const profile_collection_id = process.env.appwrite_profile_collection_id || '';</span>
Diese Datei lädt Umgebungsvariablen aus einer .Env -Datei und exportiert sie als Konstanten für die Verwendung in der Anwendung, z. B. Appwrite- und Genehmigungskonfigurationen, Datenbank -IDs und Sammel -IDs. Standardwerte werden als Fallbacks bereitgestellt, wenn die Umgebungsvariablen nicht festgelegt sind.
- API -Ordner
- Erstellen Sie Student.ts und fügen Sie den folgenden Code ein:
<span>Express aus "Express" importieren; </span><span>importieren {createstudent, fetchstudents} aus '../controllers/student'; </span><span>AuthMiddleware aus '../middleware/Auth' importieren; </span> <span>const router = express.router (); </span> <span>// Endpunkte des Schülers definieren </span>Router <span>.post ('/student', Authmiddleware, Createstudent); // Erstellen Sie einen neuen Schüler </span>Router <span>.get ('/student/: mail', authmiddleware, fetchstudents); // Alle Schüler holen </span><span>Standard -Router exportieren; // die Routerinstanz exportieren</span>
Diese Datei legt einen Express -Router mit Endpunkten für die Verwaltung von Studentendaten ein. Es enthält Routen zum Erstellen eines neuen Schülers und zum Abrufen von Schülern, die beide durch eine Authentifizierung Middleware (Authmiddleware) geschützt sind. Der Router wird dann zur Verwendung in der Anwendung exportiert.
- Erstellen Sie die Datei auth.ts und fügen Sie den folgenden Code ein:
<span>// src/routes/authroutes.ts </span><span>Express aus "Express" importieren; </span><span>Importieren {Anmeldung, Login, Logout} aus '../controllers/Auth'; </span> <span>const router = express.router (); </span> <span>// authbezogene Endpunkte definieren </span>Router <span>.post ('/Signup', (Req, Res, Next) => {// Anmelderoute </span><span>Anmeldung (req, res) .then (() => { </span><span>nächste(); </span><span>}). catch ((err) => { </span><span>Weiter (arr); </span><span>}); </span><span>}); </span>Router <span>.post ('/login', (req, res, next) => {// Anmelderoute </span><span>Login (req, res) .then (() => { </span><span>nächste(); </span><span>}). catch ((err) => { </span><span>Weiter (arr); </span><span>}); </span><span>}); </span>Router <span>.post ('/logout', logout); // Abmelderoute </span><span>Standard -Router exportieren; // die Routerinstanz exportieren</span>
Diese Datei legt einen Express-Router mit Endpunkten für authentifizierungsbezogene Aktionen ein, einschließlich Benutzeranmeldung, Anmeldung und Abmelden. Die Anmeldungs- und Anmelderouten verarbeiten asynchrone Operationen mit Fehlerbehandlung, während die Abmelderoute unkompliziert ist. Der Router wird zur Verwendung in der Anwendung exportiert.
- Datei zuweisen.ts Datei erstellen und fügen Sie den folgenden Code ein:
<span>Express aus "Express" importieren </span><span>importieren {createassignment, fetchaTsignments} aus "../controllers/assisignment" " </span><span>Importieren Sie AuthMiddleware aus "../Middleware/Auth" </span> <span>const router = express.router () </span> Router <span>.post ("/create", Authmiddleware, Createassignment) </span>Router <span>.Get ("/: E -Mail", Authmiddleware, FetchaSsignments) </span><span>Standard -Router exportieren</span>
Diese Datei legt einen Express -Router mit Endpunkten für die Verwaltung von Zuweisungen ein. Es enthält Routen zum Erstellen einer Zuordnung und zum Abrufen von Zuweisungen, die beide durch eine Authentifizierung Middleware (Authmiddleware) geschützt sind. Der Router wird zur Verwendung in der Anwendung exportiert.
- Datei profile.ts erstellen und fügen Sie den folgenden Code ein:
<span>Express aus "Express" importieren; </span><span>Import {createProfile, getProfileByemail} aus '../controllers/profile'; </span><span>AuthMiddleware aus '../middleware/Auth' importieren; </span> <span>const router = express.router (); </span> <span>// Route zum Erstellen eines Profils </span>Router <span>.post ('/profil', authmiddleware, createProfile); </span> <span>// Route zum Erhalten eines Profils per E -Mail </span>Router <span>.get ('/profile/: mail', authmiddleware, getProfilebyemail); </span><span>Standard -Router exportieren;</span>
This file sets up an Express router with endpoints for managing user profiles. It includes routes for creating a profile and fetching a profile by email, both protected by an authentication middleware (authMiddleware). The router is exported for use in the application.
- Create index.ts file and paste the following code:
<span>import express, { Request, Response } from 'express'; </span><span>import dotenv from 'dotenv'; </span><span>import cors from 'cors'; // CORS middleware </span><span>import authRoutes from './auth'; // Import auth routes </span><span>import profileRoutes from './profile'; </span><span>import studentRoutes from './student'; </span><span>import assignmentRoutes from './assignment'; </span><span>import { errorHandler } from '../utils/errorHandler'; // Custom error handler middleware </span> dotenv <span>.config(); // Load environment variables from .env file </span> <span>const app = express(); </span><span>const PORT = process.env.PORT || 8080; </span> <span>// Middleware </span>app <span>.use(cors()); // Handle CORS </span>app <span>.use(express.json()); /// Parse incoming JSON requests </span> <span>// Routes </span>app <span>.use('/api/auth', authRoutes); // Authentication routes </span>app <span>.use('/api', profileRoutes); // Profile routes mounted </span>app <span>.use('/api', studentRoutes); // Student routes mounted </span>app <span>.use('/api/assignments', assignmentRoutes); // Assignment routes mounted </span> <span>// Global Error Handling Middleware </span>app <span>.use(errorHandler); // Handle errors globally </span> <span>// Default Route </span>app <span>.get('/', (req: Request, res: Response) => { </span> res <span>.send('Appwrite Express API'); </span><span>}); </span> <span>// Start Server </span>app <span>.listen(PORT, () => { </span><span>console.log( <span>`Server is running on port <span>${PORT}</span> `</span> ); </span><span>}); </span><span>export default app;</span>
This file sets up an Express server, configuring middleware like CORS and JSON parsing, and mounts routes for authentication, profiles, students, and assignments. It includes a global error handler and a default route to confirm the server is running. The server listens on a specified port, logs its status, and exports the app instance for further use.
- Finally, to run this project, change a part of package.json and install the following packages below so when you run npm run dev, it works.
- Install packages:
npm install concurrently ts-node nodemon --save-dev
- By updating the scripts in the package.json, when you start the server, the typescript files are compiled to JavaScript in a new folder that is automatically created called dist
"scripts": { "dev": "concurrently \"tsc --watch\" \"nodemon -q --watch src --ext ts --exec ts-node src/api/index.ts\"", "build": "tsc", "start": "node ./dist/api/index.js" },
Now run npm run dev to start your server. When you see this message, it means that you have successfully implemented the backend.

Congratulations, your backend is ready for requests.
Now that our backend is set up, move on to frontend integration, where you'll:
- Secure API requests from Next.js
- Dynamically show/hide UI elements based on user permissions.
Reason for creating an extensive backend service using Appwrite
Appwrite is often described as a backend-as-a-service (BaaS) solution, meaning it provides ready-made backend functionality like authentication, database management, and storage without requiring developers to build a traditional backend.
However, for this project, I needed more flexibility and control over how data was processed, secured, and structured, which led me to create an extensive custom backend using Node.js and Express while still leveraging Appwrite's services.
Instead of relying solely on Appwrite's built-in API calls from the frontend, I designed a Node.js backend that acted as an intermediary between the frontend and Appwrite. This allowed me to:
- Implement fine-grained access control with Permit.io before forwarding requests to Appwrite.
- Structure API endpoints for multi-tenancy to ensure tenant-specific data isolation.
- Create custom business logic, such as processing role-based actions before committing them to the Appwrite database.
- Maintain a centralized API layer, making it easier to enforce security policies, log activities, and scale the application.
Appwrite provided the core authentication and database functionality of this application, but this additional backend layer enhanced security, flexibility, and maintainability, to ensure strict access control before any action reached Appwrite.
Abschluss
That's it for part one of this article series. In part 2, we'll handle the frontend integration by setting up API calls with authorization, initializing and installing necessary dependencies, writing out the component file codes, and handling state management & routes.
Das obige ist der detaillierte Inhalt vonErstellen einer SaaS-Anwendung mit mehreren Mietern mit Next.js (Backend Integration). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Zu den Anwendungen von JavaScript in der realen Welt gehören die serverseitige Programmierung, die Entwicklung mobiler Anwendungen und das Internet der Dinge. Die serverseitige Programmierung wird über node.js realisiert, die für die hohe gleichzeitige Anfrageverarbeitung geeignet sind. 2. Die Entwicklung der mobilen Anwendungen erfolgt durch reaktnative und unterstützt die plattformübergreifende Bereitstellung. 3.. Wird für die Steuerung von IoT-Geräten über die Johnny-Five-Bibliothek verwendet, geeignet für Hardware-Interaktion.

Ich habe eine funktionale SaaS-Anwendung mit mehreren Mandanten (eine EdTech-App) mit Ihrem täglichen Tech-Tool erstellt und Sie können dasselbe tun. Was ist eine SaaS-Anwendung mit mehreren Mietern? Mit Multi-Tenant-SaaS-Anwendungen können Sie mehrere Kunden aus einem Sing bedienen

Dieser Artikel zeigt die Frontend -Integration mit einem Backend, das durch die Genehmigung gesichert ist und eine funktionale edtech SaaS -Anwendung unter Verwendung von Next.js. erstellt. Die Frontend erfasst Benutzerberechtigungen zur Steuerung der UI-Sichtbarkeit und stellt sicher, dass API-Anfragen die Rollenbasis einhalten

JavaScript ist die Kernsprache der modernen Webentwicklung und wird für seine Vielfalt und Flexibilität häufig verwendet. 1) Front-End-Entwicklung: Erstellen Sie dynamische Webseiten und einseitige Anwendungen durch DOM-Operationen und moderne Rahmenbedingungen (wie React, Vue.js, Angular). 2) Serverseitige Entwicklung: Node.js verwendet ein nicht blockierendes E/A-Modell, um hohe Parallelitäts- und Echtzeitanwendungen zu verarbeiten. 3) Entwicklung von Mobil- und Desktop-Anwendungen: Die plattformübergreifende Entwicklung wird durch reaktnative und elektronen zur Verbesserung der Entwicklungseffizienz realisiert.

Zu den neuesten Trends im JavaScript gehören der Aufstieg von Typenkripten, die Popularität moderner Frameworks und Bibliotheken und die Anwendung der WebAssembly. Zukunftsaussichten umfassen leistungsfähigere Typsysteme, die Entwicklung des serverseitigen JavaScript, die Erweiterung der künstlichen Intelligenz und des maschinellen Lernens sowie das Potenzial von IoT und Edge Computing.

JavaScript ist der Eckpfeiler der modernen Webentwicklung. Zu den Hauptfunktionen gehören eine ereignisorientierte Programmierung, die Erzeugung der dynamischen Inhalte und die asynchrone Programmierung. 1) Ereignisgesteuerte Programmierung ermöglicht es Webseiten, sich dynamisch entsprechend den Benutzeroperationen zu ändern. 2) Die dynamische Inhaltsgenerierung ermöglicht die Anpassung der Seiteninhalte gemäß den Bedingungen. 3) Asynchrone Programmierung stellt sicher, dass die Benutzeroberfläche nicht blockiert ist. JavaScript wird häufig in der Webinteraktion, der einseitigen Anwendung und der serverseitigen Entwicklung verwendet, wodurch die Flexibilität der Benutzererfahrung und die plattformübergreifende Entwicklung erheblich verbessert wird.

Python eignet sich besser für Datenwissenschaft und maschinelles Lernen, während JavaScript besser für die Entwicklung von Front-End- und Vollstapel geeignet ist. 1. Python ist bekannt für seine prägnante Syntax- und Rich -Bibliotheks -Ökosystems und ist für die Datenanalyse und die Webentwicklung geeignet. 2. JavaScript ist der Kern der Front-End-Entwicklung. Node.js unterstützt die serverseitige Programmierung und eignet sich für die Entwicklung der Vollstapel.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Dreamweaver Mac
Visuelle Webentwicklungstools

MinGW – Minimalistisches GNU für Windows
Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.

SAP NetWeaver Server-Adapter für Eclipse
Integrieren Sie Eclipse mit dem SAP NetWeaver-Anwendungsserver.

VSCode Windows 64-Bit-Download
Ein kostenloser und leistungsstarker IDE-Editor von Microsoft

PHPStorm Mac-Version
Das neueste (2018.2.1) professionelle, integrierte PHP-Entwicklungstool