Besonderheiten
TypeORM
Für die Erstellung der PostgresSQl-Tabellen für die FrEDA-App wie Nutzer, Rollen, Geräte o.ä. wird das Framework
TypeORM genutzt. Dieses ermöglicht über Code-First und TypeScript Tabellen-Schemas zu spezifizieren. Beim Einrichten
des Freda-Frameworks wird über yarn setup das Einrichten der Tabellen vorgenommen. Über TypeORM lassen sich
auch Daten abfragen/ändern/löschen. Aufgrund der Verwendung von GraphQL-Bindings wurde diese Art von
Datenmanipulation jedoch in den meisten Fällen umgangen, um die Nutzung des Freda-Framworks an den meisten
stellen einheitlich zu halten, als wäre die interne Datenverwaltung ein externer Datenservice.
Für eine ausführliche Doku von TypeORM bitte folgende Seite besuchen: https://typeorm.io
GraphQL-Binding
Über GraphQL-Binding können interne Abfragen in Resolvern oder Providern auf Datenbanken durchgeführt werden. Hierzu gibt es ein extra GraphQL-Module, welches per Dependency-Injection in die jeweiligen unter GraphQL-Modules durchgereicht wird. Siehe:
backend/freda-middleware/src/modules/fredaGraphQLProxy/index.module.ts
export const getFredaGraphQLProxyModule = (fredaGraphQlSchema: GraphQLSchema) => {
const mergedSchema = mergeSchemas({
schemas: [
fredaGraphQlSchema,
],
});
const fredaGraphQlSchemaBinding = new Binding({schema: mergedSchema});
return new GraphQLModule({
name: 'fredaGraphQLProxy',
providers: () => [{
provide: 'fredaGraphQlSchemaBinding',
useValue: fredaGraphQlSchemaBinding,
}],
extraSchemas: () => [
mergedSchema,
],
resolversComposition: {
'Mutation.deleteUserById': [preventDeleteMiddleware(1, 'Nutzer mit der ID 1 kann nicht gelöscht werden!')],
'Mutation.deleteRoleById': [preventDeleteMiddleware(1, 'Rolle mit der ID 1 kann nicht gelöscht werden!')],
},
});
};
Das Modul erlaubt es, auf Freda-Nutzerdaten über folgende interne Queries mit folgender Syntax zuzugreifen:
const fragment = `fragment EnsureFullName on User { nodeId id password firstName lastName email userRolesRolesByUserId { nodes { roleByRoleId { nodeId id name } } } }`;
const graphileUser = await this._binding.query.userByEmail({email}, addFragmentToInfo(info, fragment));
Das Beispiel fragt einen Nutzer per Mail ab. Das nötige Modul dafür ist graphql-binding, welches vorab importiert
werden muss.
Ähnliche Ansätze gibt es hier:
- VulcanoJs: GraphQl-Server Framework: https://docs.vulcanjs.org/server-queries.html
- PrismaJS: ORM-Like Framwork für GraphQL und mehr: https://www.prisma.io/
GraphQL-Transforming
Für das Änderung von GraphQl-Schemas wird das Tool "graphql-tools" genutzt.
Details hierzu findet man hier: https://www.graphql-tools.com/
PubSub
PubSub ist ein Mechanismus, der es erlaubt Events über ein EventSystem an die Infrastruktur zu übermitteln. Damit lassen sich bspw. Logging-Events triggern, welche auch per Echtzeit und GraphQL-Subscription an den Clint weiterreichen lassen. Auch Chat-Funktionen o.ä. lassen sich damit umsetzen. Als Basis-Evetsystem gibt es mehrere Möglichkeiten, sogennante Communication-Bridges, siehe:
Freda verwendet aktuell die Implentierung einer Communication-Bridges von Postgres. Hier ist diese Implementiert als GraphQL-Module backend/freda-middleware/src/modules/common/index.module.ts
import { GraphQLModule } from '@graphql-modules/core';
import { ProviderScope } from '@graphql-modules/di';
import { PubSub } from 'graphql-subscriptions';
const { PostgresPubSub } = require('graphql-postgres-subscriptions');
const pubsub = new PostgresPubSub({
host: process.env.FREDA_DB_HOST,
port: process.env.FREDA_DB_PORT,
user: process.env.FREDA_DB_USERNAME,
password: process.env.FREDA_DB_PASSWORD,
database: process.env.FREDA_DB_NAME,
schema:process.env.FREDA_DB_SCHEMA
});
export const commonModule = new GraphQLModule({
name: 'common',
providers: () => [
{
provide: PubSub,
scope: ProviderScope.Application,
useValue: pubsub,
},
],
});
JWT-Token
Ein JWT Token wird für die Authentifizierung genutzt. Er beinhaltet alle wesentlichen Daten und kann nur mithilfe eines Schlüssel serverseitig verifiziert werden.
Genaue Infos dazu findet man hier: https://jwt.io/
Cookie-Auth
Aktuell verwendet der GraphQL-Gateway-Server Cookie-Authentifizierung. D.h. der JWT Token wird bei jedem Request im Header als Cookie-Set mitgeliefert. Ein Auth-Cookie ist dabei immer an seine HauptDomain gekoppelt, weshalb die Authentifizierung über mehrere Anwendungen, welche die gleiche Basis-Domain beinhalten, geteilt werden kann.
Das ist auch der Grund warum sowohl die freda-app als auch die freda-adminui mit einem einzigen Login bedienbar ist.
Überlegung ist hier auf eine Header-Auth zu wechseln, da so auch andere Anwednungen außerhalb eines Browser in der Lage sind, sich gegen den GraphQL-Gateway zu authentifizieren, was mit der aktuellen Lösung und Umsetzung nicht möglich wäre.
