Skip to content

fix: tell the user why NUITEQ refused, not which request it refused - #75

Merged
oleksandr-nc merged 1 commit into
mainfrom
fix/nuiteq-api-errors
Oct 21, 2026
Merged

oleksandr-nc merged 1 commit into
mainfrom
fix/nuiteq-api-errors

Conversation

@oleksandr-nc

@oleksandr-nc oleksandr-nc commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #71 and #74, after which the toasts for listing, creating and deleting boards, and those of the settings, show whatever reason the server hands back. For a request NUITEQ refused, that reason was Guzzle's message naming the request, unless the refusal was a 403 with a JSON object or array.

A refused login showed the request that failed

NUITEQ answers an unknown username and password with a 401 and its reason, {"error":"Invalid username or password"}. Nextcloud's client throws on an answer of 400 or above, and for every refusal but a 403 with a JSON object or array, both login() and request() handed back the exception's own message instead: Guzzle's English, naming the request that failed. That login showed in the personal settings as

Client error: `POST https://nuiteqstage.se/api/v1/login` resulted in a `401 Unauthorized` response:
{"error":"Invalid username or password"}

The settings after a login, and the toasts after listing, creating and deleting boards, now show NUITEQ's reason, the error of its JSON answer, when it gives one, and otherwise the status: "Login failed: the NUITEQ Stage URL answered 401" or "The NUITEQ Stage URL answered 500". Without NUITEQ's reason a 401 or a 403 may come from a proxy or a firewall, so it is not told as a verdict on the credentials. The exception's message goes to the log, where the URL and the status are worth having.

A 403 without a reason is a refusal too

A 403 with a JSON object or array as its body was handed back as NUITEQ wrote it. The 403 NUITEQ answers a key it does not know with carries an error, so it was handed back as a refusal. Without one, a deletion NUITEQ refused read as success and took the board off the list. It is a refusal like any other now.

Guzzle is a dev dependency of the tests

The catch blocks are tested with the exceptions Guzzle itself builds, whose message is the one Nextcloud's client carries and the log now reads. A clone on its own has no Guzzle; CI runs the tests inside a server checkout, which ships Guzzle itself. Psalm finds Guzzle's classes in vendor/ now, so the UndefinedClass suppression for them suppresses nothing, which psalm reports as an error. The two classes beside them are ones nothing in lib/ refers to, so the suppression goes whole.

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@oleksandr-nc
oleksandr-nc force-pushed the fix/nuiteq-api-errors branch 7 times, most recently from 8bd86a6 to 9d89f81 Compare October 21, 2026 08:52
NUITEQ answers an unknown username and password with a 401 and its
reason, {"error":"Invalid username or password"}. Nextcloud's client
throws on an answer of 400 or above, and for every refusal but a 403
with a JSON object or array, both login() and request() handed back the
exception's own message instead. That is Guzzle's English, naming the
request that failed, so that login showed in the personal settings as

    Client error: `POST https://nuiteqstage.se/api/v1/login` resulted
    in a `401 Unauthorized` response:
    {"error":"Invalid username or password"}

The settings after a login, and the toasts after listing, creating and
deleting boards, now show NUITEQ's reason, the error of its JSON answer,
when it gives one, and otherwise the status: "Login failed: the NUITEQ
Stage URL answered 401" or "The NUITEQ Stage URL answered 500". Without
NUITEQ's reason a 401 or a 403 may come from a proxy or a firewall, so
it is not told as a verdict on the credentials. The exception's message
goes to the log, where the URL and the status are worth having.

A 403 with a JSON object or array as its body was handed back as NUITEQ
wrote it. The 403 NUITEQ answers a key it does not know with carries an
error, so it was handed back as a refusal. Without one, a deletion
NUITEQ refused read as success and took the board off the list. It is a
refusal like any other now.

The catch blocks are tested with the exceptions Guzzle itself builds,
whose message is the one Nextcloud's client carries and the log now
reads. A clone on its own has no Guzzle, so it is a dev dependency of
the tests; CI runs them inside a server checkout, which ships Guzzle
itself. Psalm finds Guzzle's classes in vendor/ now, so the
UndefinedClass suppression for them suppresses nothing, which psalm
reports as an error. The two classes beside them are ones nothing in
lib/ refers to, so the suppression goes whole.

Signed-off-by: Oleksander Piskun <oleksandr2088@icloud.com>
@oleksandr-nc
oleksandr-nc force-pushed the fix/nuiteq-api-errors branch from 9d89f81 to bdf4922 Compare October 21, 2026 09:11
@oleksandr-nc
oleksandr-nc merged commit 101ed94 into main Oct 21, 2026
26 checks passed
@oleksandr-nc
oleksandr-nc deleted the fix/nuiteq-api-errors branch October 21, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant