KeyHelp API  [GELÖST]

User avatar
Alexander
Keyweb AG
Posts: 4448
Joined: Wed 20. Jan 2016, 02:23

Re: KeyHelp API

Post by Alexander »

Nicht wundern, ich bereite die Server doch erst am Montagmorgen vor. Bis dahin können sich aber trotzdem noch gern Test-Willige melden.
Mit freundlichen Grüßen / Best regards
Alexander Mahr

**************************************************************
Keyweb AG - Die Hosting Marke
Neuwerkstr. 45/46, 99084 Erfurt / Germany
http://www.keyweb.de - http://www.keyhelp.de
**************************************************************
User avatar
OlliTheDarkness
Posts: 1868
Joined: Tue 14. Aug 2018, 16:41
Location: Essen (NRW)

Re: KeyHelp API

Post by OlliTheDarkness »

Alexander wrote: Fri 27. Sep 2019, 14:58 Nicht wundern, ich bereite die Server doch erst am Montagmorgen vor. Bis dahin können sich aber trotzdem noch gern Test-Willige melden.
Na da bin ich doch dabei 8-)
Mit freundlichen Grüßen
OlliTheDarkness

**************************************************************
Helden leben lange, Legenden sterben nie

:!: World Hack Organization :!:
**************************************************************
User avatar
Tobi
Community Moderator
Posts: 3230
Joined: Thu 5. Jan 2017, 13:24

Re: KeyHelp API

Post by Tobi »

Hi Alex,
Hi @ all!

Zunächst einmal ein dickes Lob. DIe neue API ist der Hammer. Es macht damit Spaß zu arbeiten und endlich können DInge "direkt" realisiert werden welche vorher nur mit Gefrickel möglich waren. Ich freue mich schon darauf mit der API zu arbeiten, denn diese wird definitiv meinen Arbeitsalltag erleichtern. Außerdem macht sie den Weg frei für Third-Part-Software für KeyHelp. Es werden spannende Zeiten!

Folgendes ist mir bisher aufgefallen:

Erstens und wirklich (zumindest für mich) unerlässliche Ergänzung an der API => Endpoint /domain
Kannst du da bitte noch den Parameter "skeleton" hinzufügen?

Als gültigen Wert würde es reichen den jeweiligen Ordnernamen zu verwenden. Diese könnte ich ggf. manuell einpflegen.

Optimal wäre natürlich noch eine Ergänzung:
Endpont: /domain/skeleton
Methode: GET
Ergebnis: Listet die verfügbaren Ordner auf

Das "Fehlen" dieser Variable ist doppelt ungünstig, da sich nachträglich der Skeleton-Ordner-Inhalt nicht mehr in den Domain-Ordner kopieren lässt. Wir deployen aktuell eine grosse Anzahl standardisierter CMS-Start-Pakete. Es wäre einfach perfekt wenn man das passende Template ebenfalls per API bestimmen könnte.

Zweitens, Wichtigkeit Medium
Ich persönlich finde den API Key sehr "kurz". Wünschen würde ich mir eine Mindest-Schlüssellänge von 512 Bit, besser gleich 1024.

Drittens, Rückgabewert "Aktion erfolgreich"
Kann man bei der erfolgreichen Verarbeitung auch (analog zu den Fehlern) einen Statuscode (idealerweise als INT) übermitteln?
Aktuell gibt es beispielsweise folgenden Rückgabewert

Code: Select all

"code": "400 Bad Request",
Ich stelle mir eine globale Erweiterung der API vor.
Als numerischer Wert.

Code: Select all

"statuscode": 400,
und im Erfolgsfall

Code: Select all

"statuscode": 200,
Das würde das Auswerten des Rückgabewertes standardisieren.

Viertens, API Namensraum
Am Beispiel "/domains".
Je nach verwendeter Methode reagiert "/domains/{id}" anders. Könnte man hier noch folgende Alias vergeben?

Code: Select all


/domains/detail/id [GET] ===> /domains/{id} [GET]
/domains/update/id [POST] ===> /domains/{id} [PUT]
/domains/delete/id [GET] ===> /domains/{id} [DELETE]

Ich finde meine Endpointbezeichner "merkbarer" und selbsterklärend. Aber gut, das ist vielleicht einfach nur Geschmackssache.

Fünftens, Client-Overview
Quasi eine Zusammenfassung der Werte von "/clients/{id}/domains" bis "/clients/{id}/ftp-users". Im Grunde wie der Punkt "resources" bei /server
Das kann oder sollte an /clients/{id} [GET] (oder neu /clients/detail/id [GET] :D ) angehängt werden. "resources" trifft es auf den Punkt. Am besten inklusive aller Domainnamen (nicht nur die Anzahl).

Sechstens, Serverinfo
Kann man im Bereich "meta" noch IPV4 / IPV6 - Adresse hinzufügen?
Bei "operating_system" noch "eol" 1 oder 0 ergänzen? Das würde die Überwachung mehrer Server vereinfachen.
Ebenso ein "updates_in_queue". Quasi "Ausstehende Updates" für diesen Server.
"uptime" wäre auch noch ein wünschenswerter Wert.

So, mehr ist mir erstmal nicht aufgefallen 😉.
Ich freue mich auf deine / eure Rückmeldung(en).
Gruß,
Tobi


-----------------------------
wewoco.de
Das Forum für Reseller, Digital-Agenturen, Bildschirmarbeiter und Mäuseschubser
User avatar
Enigma
Posts: 258
Joined: Thu 2. Aug 2018, 19:18

Re: KeyHelp API

Post by Enigma »

Tobi wrote: Sun 20. Oct 2019, 22:11 Zunächst einmal ein dickes Lob. DIe neue API ist der Hammer. Es macht damit Spaß zu arbeiten und endlich können DInge "direkt" realisiert werden welche vorher nur mit Gefrickel möglich waren. Ich freue mich schon darauf mit der API zu arbeiten, denn diese wird definitiv meinen Arbeitsalltag erleichtern. Außerdem macht sie den Weg frei für Third-Part-Software für KeyHelp. Es werden spannende Zeiten!

Dem kann ich nur zustimmen. Mir fehlte bisher zwar die Zeit, alles komplett durchzutesten, aber alles, was ich ausprobiert habe, hat problemlos und wie erwartet funktioniert.

Tobi wrote: Sun 20. Oct 2019, 22:11 Je nach verwendeter Methode reagiert "/domains/{id}" anders.

So funktionieren REST-APIs im Normalfall... Dafür gibt es ja die unterschiedlichen "Verben". Anderenfalls wären sie unnötig.

Da Tobi die Möglichkeit anspricht, KeyHelp mit Hilfe der API zu erweitern: Das ist dann natürlich möglich, und über die KeyHelp-Datenbank kann man sich auch die User-ID zur aktuellen Session-ID beschaffen, aber man muss natürlich einige Dinge per Hand liefern, die die vorhandenen Seiten automatisch bekommen. Schön wäre es, wenn man stattdessen neue Seiten in KeyHelp registrieren könnte, die dann genauso aufgerufen werden können wie die "mitgelieferten". Die zugehörigen Dateien könnten dann z. B. mit einem Präfix im pages-Verzeichnis abgelegt werden oder auch in einem separaten Verzeichnis, das bei Updates definitiv nicht gelöscht oder modifiziert wird. Das würde es zusätzlich erleichtern, eigene Seiten einzubinden.

Gruß
Jan
This message has been ROT-13 encrypted twice for higher security.
User avatar
Alexander
Keyweb AG
Posts: 4448
Joined: Wed 20. Jan 2016, 02:23

Re: KeyHelp API

Post by Alexander »

Erst einmal vielen lieben Dank Tobi fürs Testen und den ausführlichen Bericht, und vielen Dank auch an die anderen Tester ;).
Danke für eure geopferte Zeit!

Tobi wrote: Sun 20. Oct 2019, 22:11 Erstens und wirklich (zumindest für mich) unerlässliche Ergänzung an der API => Endpoint /domain
Kannst du da bitte noch den Parameter "skeleton" hinzufügen?
Tut mir sehr leid, dass ich dich gerade bei deinem wichtigsten Punkt noch um Geduld bitten muss. Alles was mit dem Skeleton Verzeichnis in Verbindung steht wird im kommenden Update nochmal massiv überarbeitet. Aus dem Grund habe ich es auch noch nicht in die API aufgenommen, da ich zwar schon erste Pläne habe, aber noch keine 100%igen Details geplant habe.
Könntest du bis dahin trotzdem was mit der API anfangen, bzw. dir Übergangsweise noch anders behelfen?

Tobi wrote: Sun 20. Oct 2019, 22:11 Zweitens, Wichtigkeit Medium
Ich persönlich finde den API Key sehr "kurz". Wünschen würde ich mir eine Mindest-Schlüssellänge von 512 Bit, besser gleich 1024.
Habe die Schlüssellänge nun auf 128 (+1) Zeichen erweitert.

Tobi wrote: Sun 20. Oct 2019, 22:11 Drittens, Rückgabewert "Aktion erfolgreich"
Kann man bei der erfolgreichen Verarbeitung auch (analog zu den Fehlern) einen Statuscode (idealerweise als INT) übermitteln?
Aktuell gibt es beispielsweise folgenden Rückgabewert

Code: Select all

"code": "400 Bad Request",
Ich stelle mir eine globale Erweiterung der API vor.
Als numerischer Wert.

Code: Select all

"statuscode": 400,
und im Erfolgsfall

Code: Select all

"statuscode": 200,
Das würde das Auswerten des Rückgabewertes standardisieren.
Der angezeigte Statuscode entspricht dem HTTP-Status-Code, den du zurück erhältst. Du könntest, statt dem Feld generell immer den HTTP-Code auswerten. Dann hättest du es einheitlich.
Werde aber für künftige Erweiterungen der API das Ganze einmal im Hinterkopf behalten.
...Wobei z.B. beim Löschen eines Datensatzes mit HTTP Code 204 geantwortet wird ("204 No Content"). Wie der Name sagt wäre es hier per Definition nicht korrekt, mit irgendeinem Inhalt zu antworten. Ich denke aber wie gesagt noch einmal drüber nach.

Tobi wrote: Sun 20. Oct 2019, 22:11 Viertens, API Namensraum
Am Beispiel "/domains".
Je nach verwendeter Methode reagiert "/domains/{id}" anders. Könnte man hier noch folgende Alias vergeben?

Code: Select all

/domains/detail/id [GET] ===> /domains/{id} [GET]
/domains/update/id [POST] ===> /domains/{id} [PUT]
/domains/delete/id [GET] ===> /domains/{id} [DELETE]
Ich finde meine Endpointbezeichner "merkbarer" und selbsterklärend. Aber gut, das ist vielleicht einfach nur Geschmackssache.
Wie Enigma bereits sagte, würde so etwas den REST Prinzipien widersprechen.

Tobi wrote: Sun 20. Oct 2019, 22:11 Fünftens, Client-Overview
Quasi eine Zusammenfassung der Werte von "/clients/{id}/domains" bis "/clients/{id}/ftp-users". Im Grunde wie der Punkt "resources" bei /server
Das kann oder sollte an /clients/{id} [GET] (oder neu /clients/detail/id [GET] :D ) angehängt werden. "resources" trifft es auf den Punkt. Am besten inklusive aller Domainnamen (nicht nur die Anzahl).
Hier würde ich gern noch eine Nacht drüber schlafen (Feedback zum Thema wäre willkommen):
Ich würde dann die Endpunkte "/clients/{id}/domains" bis "/clients/{id}/ftp-users" entfernen, und stattdessen einen Punkt "/clients/{id}/resources" hinzufügen, über den man wie durch Tobi beschrieben sämtliche Ressourcen zurückgegeben bekommt. Wenn man bestimmte Angaben nicht braucht, könnte man sie mittels GET Query-Parameter ausblenden, z.B. "?databases=0&ftp_users=0" (sie beim Endpunkt "/server/").

Tobi wrote: Sun 20. Oct 2019, 22:11 Sechstens, Serverinfo
Kann man im Bereich "meta" noch IPV4 / IPV6 - Adresse hinzufügen?
Bei "operating_system" noch "eol" 1 oder 0 ergänzen? Das würde die Überwachung mehrer Server vereinfachen.
Ebenso ein "updates_in_queue". Quasi "Ausstehende Updates" für diesen Server.
"uptime" wäre auch noch ein wünschenswerter Wert.
Gewünschte Felder für "meta" hinzugefügt.

Code: Select all

"meta": {
        ...
        "ip_addresses": [
            "62.141...",
            "62.141..."
        ],
        ...
        "uptime": {
            "days": 80,
            "hours": 3,
            "minutes": 8,
            "seconds": 33
        },
        ...
]
Gewünschte Felder für operating_system hinzugefügt.
(Die Anzahl der Updates zu ermitteln kann 1-2 Sekunden dauern, ggf. möchte man dann via GET Query-Parameter "operating_system=0" setzen)

Code: Select all

"operating_system": {
        ...
        "end_of_life": false,
        "updates": {
            "update_count": 0,
            "security_update_count": 0,
            "reboot_required": true
        }
}

@Enigma,
Habe den zweiten Teil deines Beitrags auf meine ToDo-Liste gesetzt.
Mit freundlichen Grüßen / Best regards
Alexander Mahr

**************************************************************
Keyweb AG - Die Hosting Marke
Neuwerkstr. 45/46, 99084 Erfurt / Germany
http://www.keyweb.de - http://www.keyhelp.de
**************************************************************
User avatar
Enigma
Posts: 258
Joined: Thu 2. Aug 2018, 19:18

Re: KeyHelp API

Post by Enigma »

Alexander wrote: Mon 21. Oct 2019, 14:34
Tobi wrote: Sun 20. Oct 2019, 22:11 Fünftens, Client-Overview
Quasi eine Zusammenfassung der Werte von "/clients/{id}/domains" bis "/clients/{id}/ftp-users". Im Grunde wie der Punkt "resources" bei /server
Das kann oder sollte an /clients/{id} [GET] (oder neu /clients/detail/id [GET] :D ) angehängt werden. "resources" trifft es auf den Punkt. Am besten inklusive aller Domainnamen (nicht nur die Anzahl).
Hier würde ich gern noch eine Nacht drüber schlafen (Feedback zum Thema wäre willkommen):
Ich würde dann die Endpunkte "/clients/{id}/domains" bis "/clients/{id}/ftp-users" entfernen, und stattdessen einen Punkt "/clients/{id}/resources" hinzufügen, über den man wie durch Tobi beschrieben sämtliche Ressourcen zurückgegeben bekommt. Wenn man bestimmte Angaben nicht braucht, könnte man sie mittels GET Query-Parameter ausblenden, z.B. "?databases=0&ftp_users=0" (sie beim Endpunkt "/server/").

Das würde ich für praktischer halten, da man dann weniger Requests absetzen muss.

Alexander wrote: Mon 21. Oct 2019, 14:34 @Enigma,
Habe den zweiten Teil deines Beitrags auf meine ToDo-Liste gesetzt.

Klasse, vielen Dank!

Gruß
Jan
This message has been ROT-13 encrypted twice for higher security.
User avatar
Tobi
Community Moderator
Posts: 3230
Joined: Thu 5. Jan 2017, 13:24

Re: KeyHelp API

Post by Tobi »

Alexander wrote: Mon 21. Oct 2019, 14:34 Könntest du bis dahin trotzdem was mit der API anfangen, bzw. dir Übergangsweise noch anders behelfen?
Jein.
Klar kann ich den Rest nutzen, Benutzer, Datenbank, Domains etc. anlegen.
Das hat aber den Nachteil, dass ich den Domainpfad nicht automatisch anlegen kann.
Würde ich dies machen verhindert das das spätere Umkopieren des Skeleton-Ordners.
Also müsste ich auf das automatische Anlegen der Domain verzichten.
Alles irgendwie nix Halbes und nix Ganzes...

Daher frage ich dich nochmals (sorry) ;)
Kannst du eventuell für die Übergangszeit zum Endpoint "/domains" POST nicht doch die Option "skeleton" hinzufügen?
Dort übergeben ich dann den Pfad "_cms_start" und wenn der Pfad existiert wird kopiert. Wenn nicht, dann nicht :lol:
Somit könnte man die aktuelle Skeleton Konstrution verwenden und du kannns in Ruhe erst die neue Skeleton-Funktion vorbereiten und dann in die API integrieren. Das kann dann von mir aus erst Mitte nächstes Jahr sein.

Freue mich auf deine Antwort.

Zu 2.
Danke! Über die 512 reden wir nochmal :mrgreen:

Zu 3.
Beim Löschen eines Assets kann die API durchaus mit Code 200 antworten wenn das Löschen erfolgreich war. Das wäre stringent und zielführend.

Zu Punkt 5.
Die Endpunkte "/clients/{id}/domains" bis "/clients/{id}/ftp-users" können schon bleiben. Die brauchst du nicht zu entfernen. Mir ging es primär darum dem Kunden ein "Dashboard" basteln zu können. Da reicht es wenn angezeigt wird "5 x FTP, 20 x E-Mail Account, 3 Datenbanken". Allerdings würden die Kunden bereits im Dashboard gerne eine Auflistung aller Domainnamen sehen. Quasi wie im nativen KeyHelp Dashboard.

Zu Punkt 6.
Danke für die schnelle Umsetzung. Updates und EOL können eigentlich zwischengespeichert werden und müssen nicht jedesmal live abgefragt werden. EIne Aktualisierung einmal täglich würde mir persönlich reichen und würde die Wartepause von 1 bis 2 Sekunden eliminieren. Ich stelle mir dabei ein Server-Dashboard vor. Bei 5 Servern wäre das sonst schon eine Wartezeit von über 10 Sekunden bevor irgendwas angezeigt wird. O.K. ich könnte das auch per AJAX triggern. Dann fällt die Wartezeit vielleicht gar nicht auf. Muss ich mal selbst noch drüber nachdenken.
Gruß,
Tobi


-----------------------------
wewoco.de
Das Forum für Reseller, Digital-Agenturen, Bildschirmarbeiter und Mäuseschubser
User avatar
Alexander
Keyweb AG
Posts: 4448
Joined: Wed 20. Jan 2016, 02:23

Re: KeyHelp API

Post by Alexander »

Habe nun bei folgenden Endpunkten das Feld "skeleton" ergänzt:

[POST] /clients
[POST/PUT] /domains

Damit es beim Endpunkt /domains Wirkung zeigt, darf der Pfad für "target" noch nicht existieren. Genau wie innerhalb der KeyHelp-UI auch.
Mit freundlichen Grüßen / Best regards
Alexander Mahr

**************************************************************
Keyweb AG - Die Hosting Marke
Neuwerkstr. 45/46, 99084 Erfurt / Germany
http://www.keyweb.de - http://www.keyhelp.de
**************************************************************
User avatar
Tobi
Community Moderator
Posts: 3230
Joined: Thu 5. Jan 2017, 13:24

Re: KeyHelp API

Post by Tobi »

Wie geil!
Supi & vielen Dank!
Gruß,
Tobi


-----------------------------
wewoco.de
Das Forum für Reseller, Digital-Agenturen, Bildschirmarbeiter und Mäuseschubser
User avatar
Enigma
Posts: 258
Joined: Thu 2. Aug 2018, 19:18

Re: KeyHelp API

Post by Enigma »

Ich habe gerade keine Zeit zum Testen, daher frage ich einfach mal: Beim Anlegen einer Domain gibt es deutlich mehr Optionen als beim Updaten, z. B. php_version, is_disabled, delete_on, is_dns_disabled, is_email_domain sowie die HSTS-Einstellungen. Jedenfalls laut Doku... Ist die Doku da nur unvollständig oder kann ich diese prinzipiell nachträglich zu ändernden Optionen tatsächlich nicht per API anpassen?

Gruß
Jan
This message has been ROT-13 encrypted twice for higher security.
User avatar
Alexander
Keyweb AG
Posts: 4448
Joined: Wed 20. Jan 2016, 02:23

Re: KeyHelp API

Post by Alexander »

Ich habe gerade keine Zeit zum Testen, daher frage ich einfach mal: Beim Anlegen einer Domain gibt es deutlich mehr Optionen als beim Updaten, z. B. php_version, is_disabled, delete_on, is_dns_disabled, is_email_domain sowie die HSTS-Einstellungen. Jedenfalls laut Doku... Ist die Doku da nur unvollständig oder kann ich diese prinzipiell nachträglich zu ändernden Optionen tatsächlich nicht per API anpassen?
Grundsätzlich kannst du alle Felder, die man beim Anlegen verwenden kann auch beim Updaten verwenden. Es gibt Ausnahmen, die funktionieren aber genau wie sie es innerhalb der KeyHelp-UI tun würden.

Das heißt, wenn du eine Domain "example.com" anlegst, kannst du den Namen "example.com" nicht mehr ändern (= für PUT Requests wird das Feld "domain" ignoriert), darüber hinaus lässt sich aber so ziemlich alles andere ändern.
Oder du legst einen Benutzer mit dem Namen "test" an, dann bleibt der Benutzername für alle Zeit unveränderbar (= für PUT Requests wird das Feld "username" ignoriert), der Rest kann geändert werden.

Leider bietet der Dokumentationsstandard (openapi 3.0.2) keine mir bekannte schöne Möglichkeit, Felder nur für POST oder nur für PUT anzuzeigen. Es gibt nur die Möglichkeit zu definieren, ob ein Feld readOnly (GET) oder writeOnly (POST/PUT) ist. Aus diesem Grund hab ich mich bei den PUT-Requests nur für verkürzte Beispieldaten entschieden. Sollte das generell zur Verwirrung führen, muss später dann nochmal schauen, wie man die Verwirrung lindern kann.
Mit freundlichen Grüßen / Best regards
Alexander Mahr

**************************************************************
Keyweb AG - Die Hosting Marke
Neuwerkstr. 45/46, 99084 Erfurt / Germany
http://www.keyweb.de - http://www.keyhelp.de
**************************************************************
User avatar
Enigma
Posts: 258
Joined: Thu 2. Aug 2018, 19:18

Re: KeyHelp API

Post by Enigma »

Okay, vielen Dank für die erschöpfende Antwort! Ich hätte mich ehrlich gesagt auch gewundert, wenn es anders gewesen wäre, aber für den Moment war ich etwas verwirrt. ;)

Dann freue ich mich auf den Release-Termin, denn ich würde gern an einer größeren Anzahl Domains etwas ändern und habe keine große Lust auf die Klickerei...

Gruß
Jan
This message has been ROT-13 encrypted twice for higher security.
User avatar
Tobi
Community Moderator
Posts: 3230
Joined: Thu 5. Jan 2017, 13:24

Re: KeyHelp API

Post by Tobi »

Alexander wrote: Thu 24. Oct 2019, 08:23

Es gibt nur die Möglichkeit zu definieren, ob ein Feld readOnly (GET)
Ah. Deswegen also DELETE /domains und nicht GET /domains/delete/id

@Jan
Ja. Mit einer kombinierten API wird es dann auch möglich sein bei einem Serverwechsel Nameserver Änderungen ins DBS zu übergeben. Deswegen war mir die IP in den Server-Details wichtig.


Das wird echt Klasse mit dem nächsten Update und ich finde es toll wie Alex auf Wünsche und Ideen reagiert!
Gruß,
Tobi


-----------------------------
wewoco.de
Das Forum für Reseller, Digital-Agenturen, Bildschirmarbeiter und Mäuseschubser
User avatar
Alexander
Keyweb AG
Posts: 4448
Joined: Wed 20. Jan 2016, 02:23

Re: KeyHelp API

Post by Alexander »

Deswegen also DELETE /domains und nicht GET /domains/delete/id
Nein, das readOnly / writeOnly hat nur was mit der Dokumentation bzw. dem Dokumentationsstandard hier (https://app.swaggerhub.com/apis-docs/keyhelp/api) zu tun.

Das es "DELETE /domains" statt "GET /domains/delete/id" heißt, hat was dem REST-Paradigma zu tun. Die HTTP-Methoden geben an, was mit dem Objekt passieren soll. GET darf hierbei nur Daten liefern, keine Objekte verändern.

Z.b.: https://de.wikipedia.org/wiki/Represent ... e_Transfer - Überschrift "Umsetzung" - 3. Absatz
Das wird echt Klasse mit dem nächsten Update und ich finde es toll wie Alex auf Wünsche und Ideen reagiert!
Immer gern ;)
Mit freundlichen Grüßen / Best regards
Alexander Mahr

**************************************************************
Keyweb AG - Die Hosting Marke
Neuwerkstr. 45/46, 99084 Erfurt / Germany
http://www.keyweb.de - http://www.keyhelp.de
**************************************************************
User avatar
Tobi
Community Moderator
Posts: 3230
Joined: Thu 5. Jan 2017, 13:24

Re: KeyHelp API

Post by Tobi »

Danke für die Richtigstellung Alex.
Ich hätte ja Mal selbst auf Wikipedia kommen können 😂
Gruß,
Tobi


-----------------------------
wewoco.de
Das Forum für Reseller, Digital-Agenturen, Bildschirmarbeiter und Mäuseschubser
Locked