Gelöst /api/groups Schnittstelle liefert keine Gruppen
-
@skipy das problem liegt am page=10 ich vermute du hast nicht so viele Gruppen. Fang mal mit page=1 an ...
-
@bwl21 Das ist jetzt peinlich! Aber du hast vollkommen Recht! Ich hab den Standardparameter einfach gelassen und nicht mal darüber nachgedacht
-
@skipy sagte in /api/groups Schnittstelle liefert keine Gruppen:
Das ist jetzt peinlich
Das ist nicht peinlich ... Dafür haben wir das Forum.
-
@bwl21 Sehr Barmherzig :-). Danke.
Vielleicht kann jemand mal den Default-Wert in der openapi-Schnittstelle für page von 10 auf 1 äändern?
Derzeit heißt es da nämlich:
{ "schema": { "type": "number", "default": 10 }, "in": "query", "name": "page", "description": "Page number to show page in pagenation. If empty, start at first page." },
-
@davidschilling Es ist doch noch nicht ganz gelöst das Problem ... allerdings liegt es dieses Mal (hoffe ich) nicht an meiner Unfähigkeit :-).
Ich muste ganz schön lange debuggen, bis mir das aufgefallen ist. Es geht nach wie vor um die selbe Schnittstelle und ich glaube, da liegt ein Fehler in der Schnittstellenbeschreibung vor.
Wenn ich das richtig lese, sollte in der Schnittstellenbeschreibung das "data-property" ein Array mit mehreren einzelnen Einträgen der Gruppen sein. Doch anstelle des Arrays wird hier direkt die Beschreibung eines objects mit den direkten Gruppen-Werten angegeben.
Im Folgenden mit zwei ** markiert.
So steht es in der Openapi.json derzeit drin."responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { ** "type": "object", ** "description": "The group model structures all information in different objects: `information`, `settings`, `followUp`, and `roles`. Custom group fields are added to the root level of this model.", "properties": { "id": { "type": "integer", "example": 42 }, ...
Zum Vergleich die Beschreibung der /persons Schnittstelle
"responses": { "200": { "description": "Successful request", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { ** "type": "array", ** ** "items": { ** "title": "Person", "type": "object", "description": "A person object includes all fields the logged in user may see depending on the security level. Additional DB fields, created by the admin, are also part of the response. Those fields have the same name as the column name.", "x-tags": [ "Person" ], "properties": { "id": { "type": "integer" ...
Wenn ich das richtig lese, wurde in der Openapi Beschreibung schlichtweg eine Ebene vergessen .
Für alle PHP-Leser.
// So sieht die Spezifikation gerade aus $response = [ data => [ id => 2, ... ] ] // So SOLLTE die Spezifikation ausschauen $response = [ data => [ 0 => [id => 1, ...], 1 => [id => 2, ...] ] ]
-
@davidschilling
Hab's geprüft und mit wie nachfolgend in der openapi.json repariert - mit dieser Openapi-Definition entspricht die /groups Schnittstelle jetzt der tatsächlichen Implementation (nur die query-paramter sind noch total buggy)"/groups": { "get": { "summary": "Get all groups", "tags": [ "Group" ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "title" : "Groups", "type": "object", "x-tags" : ["Group"], "description": "The group model structures all information in different objects: `information`, `settings`, `followUp`, and `roles`. Custom group fields are added to the root level of this model.", "properties": { "id": { "type": "integer", "example": 42 }, "guid": { "type": "string", "example": "681F54E3-2EB7-40A4-84F0-EFF8E8F05727" }, "name": { "type": "string", "example": "Smallgroup West" }, "securityLevelForGroup": { "type": "integer", "description": "You can see group fields up to this security level.", "example": 3 }, "information": { "type": "object", "properties": { "imageUrl": { "default": null, "nullable": true, "type": "string" }, "dateOfFoundation": { "type": "string", "format": "date", "nullable": true }, "endDate": { "type": "string", "format": "date", "nullable": true }, "meetingTime": { "type": "string", "nullable": true }, "weekday": { "type": "integer", "nullable": true, "description": "The number of the weekday. Starting with 0 = Sunday, 1 = Monday, ..." }, "groupCategoryId": { "nullable": true, "type": "integer" }, "ageGroups": { "type": "array", "items": { "type": "integer" }, "example": [ 1, 2 ] }, "targetGroupId": { "nullable": true, "type": "integer" }, "maxMembers": { "type": "integer", "nullable": true }, "groupTypeId": { "type": "integer" }, "groupStatusId": { "type": "integer" }, "note": { "type": "string" }, "campusId": { "nullable": true, "type": "integer" }, "chatStatus": { "description": "status of group chat", "type": "string", "example": "STARTED" } } }, "settings": { "type": "object", "properties": { "isHidden": { "type": "boolean" }, "isOpenForMembers": { "description": "Indicator if people can apply for participation.", "type": "boolean" }, "autoAccept": { "description": "Indicator if applications are accepted automatically.", "type": "boolean" }, "isPublic": { "type": "boolean" }, "inStatistic": { "description": "Show in statistics.", "type": "boolean" }, "groupMeeting": { "type": "object", "properties": { "autoCreate": { "description": "Create weekly group meetings.", "type": "boolean" }, "templateId": { "description": "Group template used for meetings.", "type": "integer", "nullable": true } } }, "informLeader": { "description": "Inform leader via e-mail about changes.", "type": "boolean" }, "newMember": { "description": "Campus, Status, Department for newly created persons.", "type": "object", "nullable": true, "properties": { "campusId": { "nullable": true, "type": "integer" }, "statusId": { "nullable": true, "type": "integer" }, "departmentId": { "nullable": true, "type": "integer" } } } } }, "followUp": { "type": "object", "properties": { "typeId": { "type": "integer", "example": 1 }, "targetTypeId": { "type": "integer", "example": 0 }, "targetObjectId": { "type": "integer", "nullable": true, "example": null }, "targetGroupMemberStatusId": { "type": "integer", "nullable": true, "example": null }, "sendReminderMails": { "type": "boolean", "example": true } } }, "roles": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer", "description": "ID of this group role." }, "groupTypeRoleId": { "type": "integer", "description": "ID of the corresponding group type role." }, "groupTypeId": { "type": "integer", "description": "ID of corresponding group type." }, "name": { "type": "string", "description": "Name of role." }, "shorty": { "type": "string", "description": "Abbreviation of the name." }, "sortKey": { "type": "integer", "description": "Number used for sorting roles." }, "toDelete": { "type": "boolean", "description": "Flag, if members of this role can be deleted or removed from the group." }, "hasRequested": { "type": "boolean", "description": "Flag, if group member is requesting group access." }, "isLeader": { "type": "boolean", "description": "Flag, this role is a leader." }, "isDefault": { "type": "boolean", "description": "Indicator of default roles." }, "isHidden": { "type": "boolean", "description": "Flag, if this role is hidden in groups." }, "growPathId": { "type": "integer", "nullable": true, "description": "ID of the grow path. The id is either given from the group type role. But a group can override the grow path. In this case the group role specific ID is used." }, "forceTwoFactorAuth": { "type": "boolean", "description": "Flag, if members with this role have to use two factor authentication." }, "isActive": { "type": "boolean", "description": "Flag, if this role is active in this group." } }, "example": [ { "id": 5, "groupTypeRoleId": 3, "groupTypeId": 2, "name": "Member", "shorty": "M", "sortKey": 4, "toDelete": false, "hasRequested": false, "isLeader": false, "isDefault": true, "isHidden": false, "growPathId": null, "forceTwoFactorAuth": false, "isActive": true }, { "id": 6, "groupTypeRoleId": 4, "groupTypeId": 2, "name": "Leader", "shorty": "L", "sortKey": 2, "toDelete": false, "hasRequested": false, "isLeader": true, "isDefault": false, "isHidden": false, "growPathId": 2, "forceTwoFactorAuth": true, "isActive": true } ] }, "example": [ { "id": 5, "groupTypeRoleId": 3, "groupTypeId": 2, "name": "Member", "shorty": "M", "sortKey": 4, "toDelete": false, "hasRequested": false, "isLeader": false, "isDefault": true, "isHidden": false, "growPathId": null, "forceTwoFactorAuth": false, "isActive": true }, { "id": 6, "groupTypeRoleId": 4, "groupTypeId": 2, "name": "Leader", "shorty": "L", "sortKey": 2, "toDelete": false, "hasRequested": false, "isLeader": true, "isDefault": false, "isHidden": false, "growPathId": 2, "forceTwoFactorAuth": true, "isActive": true } ] } } } }, "ref": { "title": "MetaPagination", "type": "object", "properties": { "count": { "type": "number", "example": 10, "description": "Size of data array." }, "pagination": { "type": "object", "properties": { "total": { "type": "number", "example": 17, "description": "Count of total entities over all pages" }, "limit": { "type": "number", "default": 10, "example": 10, "description": "Current limit. How many entities are listed max in data array." }, "current": { "type": "number", "example": 1, "description": "Number of Current Page" }, "lastPage": { "type": "number", "example": 2, "description": "Number of Last Page" } } } } } } } } } } }, "operationId": "get-groups", "description": "This endpoint returns an array with all groups the user can see. This includes groups the user\n is a member of as well as subordinate groups the user is allowed to see.", "parameters": [ { "name": "ids", "schema": { "type": "array", "items": { "type": "integer" } }, "in": "query", "style": "deepObject", "description": "Array of group ids" }, { "name": "campus_ids", "in": "query", "description": "Array of campus ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "agegroup_ids", "in": "query", "description": "Array of age group ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "group_status_ids", "in": "query", "description": "Array of group status ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "group_category_ids", "in": "query", "description": "Array of group category ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "target_group_ids", "in": "query", "description": "Array of target group ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "weekdays", "in": "query", "description": "Array of weekdays to filter the groups. Sunday = 0, Monday = 1 ...", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "group_type_ids", "in": "query", "description": "Array of group type ids to filter the groups", "schema": { "type": "array", "items": { "type": "integer" } }, "style": "deepObject" }, { "name": "is_open_for_members", "in": "query", "description": "Filters groups by its open status", "schema": { "type": "boolean" } }, { "name": "is_public", "in": "query", "description": "Filters groups by its public status", "schema": { "type": "boolean" } }, { "name": "show_overdue_groups", "in": "query", "description": "Determines if groups with overdue enddate should still be shown. To the enddate x dates are added specified by the admin settings for person & groups", "schema": { "type": "boolean" } }, { "name": "show_inactive_groups", "in": "query", "description": "Determines if inactive groups should be returned", "schema": { "type": "boolean" } }, { "name": "without_my_groups", "in": "query", "description": "Determines if groups should be omitted where I am in", "schema": { "type": "boolean" } }, { "schema": { "type": "string", "minLength": 2 }, "in": "query", "name": "query" }, { "schema": { "type": "number", "default": 10 }, "in": "query", "name": "page", "description": "Page number to show page in pagenation. If empty, start at first page." }, { "schema": { "type": "number", "default": 10 }, "in": "query", "name": "limit", "description": "Number of results per page." } ] } },
Diese Definition formatiert die Ergebnisse korrekt, so dass zumindestens Alle Ergebnisse ausgelesen werden können, OHNE Parameter mitzugeben.
Bei den Parametern gibt es aber auch noch einige Schwierigkeiten. Insbesondere bei den Int Arrays (z.B. "ids", "campus_ids", usw.). Wenn ich das richtig sehe, braucht die ChurchTools API die Infos als query in dieser Form.
/?ids[]=1&ids[]=2
Als Style-Definition ist hier "deepObject" angegeben. Das ist aber nicht erlaubt. Denn "deepObject" darf nur bei "objects" verwendet werden, NICHT aber bei Arrays. Darum generiert Swagger/Openapi eine nicht funktionierende Schnittstellendefinition.
Ich finde die Idee, Openapi einzusetzen wirklich genial und hilfreich. Nur ist die Openapi Definition leider so nicht zu gebrauchen.
Wenn ich das richtig sehe, müsst ihr euch entweder entscheiden,
a) den OpenApi Standard zu verwenden (sprich querys gestatten im Format:/?ids=1,2
) oder
b) Den Parameter umbennen in"name": "ids[]"
mit der Ergänzung"style": "deepObject", "explode": true
(dann wird eine query generiert, wie sie eure API fordert. Habe das mal gedebuged und getestet)Kann jemand von churchtools team da was zur Openapi Schnittstelle sagen?
-
@skipy mir scheint, da hast du recht. Wenn man in .../api rumprobiert und ein Array von Gruppen angibt, dann wird folgende URL erzeugt
https://....church.tools/api/groups?ids=1,2,3&page=10&limit=10
aber die funktioniert nicht:
{ "message": "There are validation errors", "messageKey": "validation.error", "translatedMessage": "Die eingegebenen Daten waren nicht korrekt.", "args": [], "errors": [ { "fieldId": "ids", "message": "Die Eingabe muss ein Array sein.", "messageKey": "validation.array", "args": { "name": "ids", "value": "1,2,3" } } ] }
-
Es ist korrekt, die richtige Form der query Parameter ist
/?ids[]=1&ids[]=2
.Das haben wir schon recht lange mal entschieden, dass wir arrays in den Query-Parametern so abbilden und ich denke das ist auch weiterhin gut so. Dass die Openapi Spec das nicht korrekt abbildet ist nicht gut und deinen Hinweis, wie es in Openapi richtig geht ist da sicher hilfreich.
@skipy was meinst du mit "nur response - paramter sind noch total buggy"?
@bwl21 du nutzt hier nicht das richtige Format, mit dem oben beschriebenen sollte es funktionieren.
-
@davidschilling das ist das Format was kommt, wenn man in
mychurch.church.tools/api/groups
den "try it out" button verwendet. Ich vermute, das ist aus der Open-Api spec abgeleitet.
Wenn ich das API benutze, dann probiere ich die Abfragen immer erst mal da aus.
Ich kann nachvollziehen, dass ihr euch für
/?ids[]=1&ids[]=2.
entschieden habt, das ist zweifellos rubuster, vor allem wenn es ein array von Strings ist, die kommas enthalten können.Daher sollte das schon in der einen oder anderen Richtung korrigiert werden - vermutlich an der open-api spec.
-
@davidschilling Mit der openapi.json wird exakt definiert,
- welche Parameter eine API zur Verfügung stell
- in welcher Weise sie übertragen werden
- und auch wie sie formatiert werden.
Daraus lassen sich dann sehr einfach APIs in vielen Sprachen generieren. Das funktioniert aber nur, wenn in der openapi.json genau das beschrieben wird, was die API tut. Ansonsten wird es für die Entwickler sehr frustig .
In diesem Fall habt ihr in der openapi.json für die Schnittstelle /groups beschrieben, dass die Parameter der ids im Format
/api/groups?ids=1,2,3
übertragen werden müssen. Aber das stimmt leider nicht mit dem überein, was ihr tatsächlich wollt ...
Daraus folgt, dass alle generierten API Schnittstellen nicht funktionieren werden.- z.B. die GUI von euch
- aber auch die API die ich für PHP generiert habe, funktioniert nicht
Wie schon gesagt gibt es nur zwei Möglichkeiten:
a) Eure openapi.json Schnitstellenbeschreibung anpassen auf die Realität
b) Die Art und Weise der Parameterübergabe im API-Server so zu ändern, dass sie den API-Standards und der akuellen openapi.json entspricht.Nochmal explizit erwähnen möchte, dass nicht nur die Parameter-Definition Fehlerhaft ist, sondern auch die Rückgabewerte nicht übereinstimmen. (Siehe Post vorher mit **-Markierungen und der korrekten openapi.json Definition). Das lässt sich vermutlich am schnellsten korrigieren
-
@davidschilling sagte in /api/groups Schnittstelle liefert keine Gruppen:
@skipy was meinst du mit "nur response - paramter sind noch total buggy"?
Ich habe den Post korrigiert - was ich meinte war, dass ich die Beschreibung des API-Ergebnisses geändert habe. Ihr müsstet es nur noch übernehmen und dann stimmt das.
Die Query-Parameter stimmen allerdings noch nicht. -
@davidschilling Kannst du schon sagen, wie ihr hier gedenkt weiterzumachen und ob / bis wann ihr die Fehler in der API angeht?
Vielleicht wäre es auch eine Möglichkeit, ein öffentliches GIT-Repo zu schalten für die Openapi.json, so dass Change-Requests eingereicht werden können. Das würde das Ganze vielleicht beschleunigen?
-
Vielen Dank @skipy @bwl21 für die Hinweise. Die Fehler in der API sind sicherlich nervig, gerade wenn man richtig loslegen möchte.
Ich habe die, hier im Thread erwähnten, Dinge behoben für v3.78
/groups
Response richtig dokumentiertpage
Example Value auf 1 gesetzt- QueryParameter richtig dokumentieren