mirror of
https://github.com/zitadel/zitadel.git
synced 2025-05-01 16:20:50 +00:00
fix: add information about target response into error message if inte… (#8281)
# Which Problems Are Solved Execution responses with HTTP StatusCode not equal to 200 interrupt the client request silently. # How the Problems Are Solved Adds information about the recieved StatusCode and Body into the error if StatusCode not 200. # Additional Context Closes #8177 --------- Co-authored-by: Elio Bischof <elio@zitadel.com> Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
parent
11d01b9b35
commit
83c78a470c
@ -170,3 +170,18 @@ For event there are 3 levels the condition can be defined:
|
|||||||
- All, handling any event in ZITADEL
|
- All, handling any event in ZITADEL
|
||||||
|
|
||||||
The concept of events can be found under [Events](/concepts/architecture/software#events)
|
The concept of events can be found under [Events](/concepts/architecture/software#events)
|
||||||
|
|
||||||
|
### Error forwarding
|
||||||
|
|
||||||
|
If you want to forward a specific error from the Target through ZITADEL, you can provide a response from the Target with status code 200 and a JSON in the following format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"forwardedStatusCode": 403,
|
||||||
|
"forwardedErrorMessage": "Call is forbidden through the IP AllowList definition"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Only values from 400 to 499 will be forwarded through ZITADEL, other StatusCodes will end in a PreconditionFailed error.
|
||||||
|
|
||||||
|
If the Target returns any other status code than >= 200 and < 299, the execution is looked at as failed, and a PreconditionFailed error is logged.
|
||||||
|
@ -263,7 +263,7 @@ func TestServer_RemovePhone(t *testing.T) {
|
|||||||
req *user.RemovePhoneRequest
|
req *user.RemovePhoneRequest
|
||||||
want *user.RemovePhoneResponse
|
want *user.RemovePhoneResponse
|
||||||
wantErr bool
|
wantErr bool
|
||||||
dep func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error)
|
dep func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "remove phone",
|
name: "remove phone",
|
||||||
@ -303,7 +303,7 @@ func TestServer_RemovePhone(t *testing.T) {
|
|||||||
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
|
dep: func(ctx context.Context, userID string) (*user.RemovePhoneResponse, error) {
|
||||||
return Client.RemovePhone(ctx, &user.RemovePhoneRequest{
|
return Client.RemovePhone(ctx, &user.RemovePhoneRequest{
|
||||||
UserId: doubleRemoveUser.GetUserId(),
|
UserId: doubleRemoveUser.GetUserId(),
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -45,3 +45,36 @@ func ZitadelErrorToHTTPStatusCode(err error) (statusCode int, ok bool) {
|
|||||||
return http.StatusInternalServerError, false
|
return http.StatusInternalServerError, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HTTPStatusCodeToZitadelError(parent error, statusCode int, id string, message string) error {
|
||||||
|
if statusCode == http.StatusOK {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var errorFunc func(parent error, id, message string) error
|
||||||
|
switch statusCode {
|
||||||
|
case http.StatusConflict:
|
||||||
|
errorFunc = zerrors.ThrowAlreadyExists
|
||||||
|
case http.StatusGatewayTimeout:
|
||||||
|
errorFunc = zerrors.ThrowDeadlineExceeded
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
errorFunc = zerrors.ThrowInternal
|
||||||
|
case http.StatusBadRequest:
|
||||||
|
errorFunc = zerrors.ThrowInvalidArgument
|
||||||
|
case http.StatusNotFound:
|
||||||
|
errorFunc = zerrors.ThrowNotFound
|
||||||
|
case http.StatusForbidden:
|
||||||
|
errorFunc = zerrors.ThrowPermissionDenied
|
||||||
|
case http.StatusUnauthorized:
|
||||||
|
errorFunc = zerrors.ThrowUnauthenticated
|
||||||
|
case http.StatusServiceUnavailable:
|
||||||
|
errorFunc = zerrors.ThrowUnavailable
|
||||||
|
case http.StatusNotImplemented:
|
||||||
|
errorFunc = zerrors.ThrowUnimplemented
|
||||||
|
case http.StatusTooManyRequests:
|
||||||
|
errorFunc = zerrors.ThrowResourceExhausted
|
||||||
|
default:
|
||||||
|
errorFunc = zerrors.ThrowUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorFunc(parent, id, message)
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -136,3 +138,152 @@ func TestZitadelErrorToHTTPStatusCode(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHTTPStatusCodeToZitadelError(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
statusCode int
|
||||||
|
id string
|
||||||
|
message string
|
||||||
|
parent error
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "StatusOK",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusOK,
|
||||||
|
},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusConflict",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusConflict,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowAlreadyExists(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusGatewayTimeout",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusGatewayTimeout,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowDeadlineExceeded(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusInternalServerError",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusInternalServerError,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowInternal(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusBadRequest",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusBadRequest,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowInvalidArgument(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusNotFound",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusNotFound,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowNotFound(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusForbidden",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusForbidden,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowPermissionDenied(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusUnauthorized",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusUnauthorized,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowUnauthenticated(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusServiceUnavailable",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusServiceUnavailable,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowUnavailable(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusNotImplemented",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusNotImplemented,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowUnimplemented(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "StatusTooManyRequests",
|
||||||
|
args: args{
|
||||||
|
statusCode: http.StatusTooManyRequests,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowResourceExhausted(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unknown",
|
||||||
|
args: args{
|
||||||
|
statusCode: 1000,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowUnknown(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unknown, test for statuscode",
|
||||||
|
args: args{
|
||||||
|
statusCode: 1000,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowError(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unknown with parent",
|
||||||
|
args: args{
|
||||||
|
statusCode: 1000,
|
||||||
|
id: "id",
|
||||||
|
message: "message",
|
||||||
|
parent: errors.New("parent error"),
|
||||||
|
},
|
||||||
|
wantErr: zerrors.ThrowUnknown(nil, "id", "message"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := HTTPStatusCodeToZitadelError(tt.args.parent, tt.args.statusCode, tt.args.id, tt.args.message)
|
||||||
|
assert.ErrorIs(t, err, tt.wantErr)
|
||||||
|
if tt.args.parent != nil {
|
||||||
|
assert.ErrorIs(t, err, tt.args.parent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,12 +3,14 @@ package execution
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zitadel/logging"
|
"github.com/zitadel/logging"
|
||||||
|
|
||||||
|
zhttp "github.com/zitadel/zitadel/internal/api/http"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
@ -114,9 +116,35 @@ func Call(ctx context.Context, url string, timeout time.Duration, body []byte) (
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return HandleResponse(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleResponse(resp *http.Response) ([]byte, error) {
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// Check for success between 200 and 299, redirect 300 to 399 is handled by the client, return error with statusCode >= 400
|
// Check for success between 200 and 299, redirect 300 to 399 is handled by the client, return error with statusCode >= 400
|
||||||
if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
|
if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
|
||||||
return io.ReadAll(resp.Body)
|
var errorBody ErrorBody
|
||||||
|
if err := json.Unmarshal(data, &errorBody); err != nil {
|
||||||
|
// if json unmarshal fails, body has no ErrorBody information, so will be taken as successful response
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
if errorBody.ForwardedStatusCode != 0 || errorBody.ForwardedErrorMessage != "" {
|
||||||
|
if errorBody.ForwardedStatusCode >= 400 && errorBody.ForwardedStatusCode < 500 {
|
||||||
|
return nil, zhttp.HTTPStatusCodeToZitadelError(nil, errorBody.ForwardedStatusCode, "EXEC-reUaUZCzCp", errorBody.ForwardedErrorMessage)
|
||||||
|
}
|
||||||
|
return nil, zerrors.ThrowPreconditionFailed(nil, "EXEC-bmhNhpcqpF", errorBody.ForwardedErrorMessage)
|
||||||
|
}
|
||||||
|
// no ErrorBody filled in response, so will be taken as successful response
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
return nil, zerrors.ThrowUnknown(nil, "EXEC-dra6yamk98", "Errors.Execution.Failed")
|
|
||||||
|
return nil, zerrors.ThrowPreconditionFailed(nil, "EXEC-dra6yamk98", "Errors.Execution.Failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorBody struct {
|
||||||
|
ForwardedStatusCode int `json:"forwardedStatusCode,omitempty"`
|
||||||
|
ForwardedErrorMessage string `json:"forwardedErrorMessage,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package execution_test
|
package execution_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -15,6 +18,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/api/grpc/server/middleware"
|
"github.com/zitadel/zitadel/internal/api/grpc/server/middleware"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
"github.com/zitadel/zitadel/internal/execution"
|
"github.com/zitadel/zitadel/internal/execution"
|
||||||
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Call(t *testing.T) {
|
func Test_Call(t *testing.T) {
|
||||||
@ -513,3 +517,152 @@ var requestContextInfoBody2 = []byte("{\"request\":{\"request\":\"content2\"}}")
|
|||||||
type request struct {
|
type request struct {
|
||||||
Request string `json:"request"`
|
Request string `json:"request"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testErrorBody(code int, message string) []byte {
|
||||||
|
body := &execution.ErrorBody{ForwardedStatusCode: code, ForwardedErrorMessage: message}
|
||||||
|
data, _ := json.Marshal(body)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handleResponse(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
resp *http.Response
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
data []byte
|
||||||
|
wantErr func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"response, statuscode unknown and body",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: 1000,
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte(""))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "EXEC-dra6yamk98", "Errors.Execution.Failed"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode >= 400 and no body",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusForbidden,
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte(""))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "EXEC-dra6yamk98", "Errors.Execution.Failed"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode >= 400 and body",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusForbidden,
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte("body"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "EXEC-dra6yamk98", "Errors.Execution.Failed"))
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode = 200 and body",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte("body"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
data: []byte("body"),
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode = 200 no body",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewReader([]byte(""))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
data: []byte(""),
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode = 200, error body >= 400 < 500",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewReader(testErrorBody(http.StatusForbidden, "forbidden"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "EXEC-reUaUZCzCp", "forbidden"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode = 200, error body >= 500",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewReader(testErrorBody(http.StatusInternalServerError, "internal"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "EXEC-bmhNhpcqpF", "internal"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"response, statuscode = 308, no body, should not happen",
|
||||||
|
args{
|
||||||
|
resp: &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
Body: io.NopCloser(bytes.NewReader(testErrorBody(http.StatusPermanentRedirect, "redirect"))),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
wantErr: func(err error) bool {
|
||||||
|
return errors.Is(err, zerrors.ThrowPreconditionFailed(nil, "EXEC-bmhNhpcqpF", "redirect"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
respBody, err := execution.HandleResponse(
|
||||||
|
tt.args.resp,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tt.res.wantErr == nil {
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
} else if !tt.res.wantErr(err) {
|
||||||
|
t.Errorf("got wrong err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.res.data, respBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -581,6 +581,7 @@ Errors:
|
|||||||
NotFound: Изпълнението не е намерено
|
NotFound: Изпълнението не е намерено
|
||||||
IncludeNotFound: Включването не е намерено
|
IncludeNotFound: Включването не е намерено
|
||||||
NoTargets: Няма определени цели
|
NoTargets: Няма определени цели
|
||||||
|
Failed: неуспешно изпълнение
|
||||||
ResponseIsNotValidJSON: Отговорът не е валиден JSON
|
ResponseIsNotValidJSON: Отговорът не е валиден JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Функцията „Потребителска схема“ не е активирана
|
NotEnabled: Функцията „Потребителска схема“ не е активирана
|
||||||
|
@ -562,6 +562,7 @@ Errors:
|
|||||||
NotFound: Provedení nenalezeno
|
NotFound: Provedení nenalezeno
|
||||||
IncludeNotFound: Zahrnout nenalezeno
|
IncludeNotFound: Zahrnout nenalezeno
|
||||||
NoTargets: Nejsou definovány žádné cíle
|
NoTargets: Nejsou definovány žádné cíle
|
||||||
|
Failed: Provedení se nezdařilo
|
||||||
ResponseIsNotValidJSON: Odpověď není platný JSON
|
ResponseIsNotValidJSON: Odpověď není platný JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Funkce "Uživatelské schéma" není povolena
|
NotEnabled: Funkce "Uživatelské schéma" není povolena
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Ausführung nicht gefunden
|
NotFound: Ausführung nicht gefunden
|
||||||
IncludeNotFound: Einschließen nicht gefunden
|
IncludeNotFound: Einschließen nicht gefunden
|
||||||
NoTargets: Keine Ziele definiert
|
NoTargets: Keine Ziele definiert
|
||||||
|
Failed: Ausführung fehlgeschlagen
|
||||||
ResponseIsNotValidJSON: Antwort ist kein gültiges JSON
|
ResponseIsNotValidJSON: Antwort ist kein gültiges JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Funktion Benutzerschema ist nicht aktiviert
|
NotEnabled: Funktion Benutzerschema ist nicht aktiviert
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Execution not found
|
NotFound: Execution not found
|
||||||
IncludeNotFound: Include not found
|
IncludeNotFound: Include not found
|
||||||
NoTargets: No targets defined
|
NoTargets: No targets defined
|
||||||
|
Failed: Execution failed
|
||||||
ResponseIsNotValidJSON: Response is not valid JSON
|
ResponseIsNotValidJSON: Response is not valid JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Feature "User Schema" is not enabled
|
NotEnabled: Feature "User Schema" is not enabled
|
||||||
@ -594,7 +595,6 @@ Errors:
|
|||||||
NoActive: No active web key found
|
NoActive: No active web key found
|
||||||
NotFound: Web key not found
|
NotFound: Web key not found
|
||||||
|
|
||||||
|
|
||||||
AggregateTypes:
|
AggregateTypes:
|
||||||
action: Action
|
action: Action
|
||||||
instance: Instance
|
instance: Instance
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Ejecución no encontrada
|
NotFound: Ejecución no encontrada
|
||||||
IncludeNotFound: Incluir no encontrado
|
IncludeNotFound: Incluir no encontrado
|
||||||
NoTargets: No hay objetivos definidos
|
NoTargets: No hay objetivos definidos
|
||||||
|
Failed: Ejecución fallida
|
||||||
ResponseIsNotValidJSON: La respuesta no es un JSON válido
|
ResponseIsNotValidJSON: La respuesta no es un JSON válido
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: La función "Esquema de usuario" no está habilitada
|
NotEnabled: La función "Esquema de usuario" no está habilitada
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Exécution introuvable
|
NotFound: Exécution introuvable
|
||||||
IncludeNotFound: Inclure introuvable
|
IncludeNotFound: Inclure introuvable
|
||||||
NoTargets: Aucune cible définie
|
NoTargets: Aucune cible définie
|
||||||
|
Failed: Exécution échouée
|
||||||
ResponseIsNotValidJSON: La réponse n'est pas un JSON valide
|
ResponseIsNotValidJSON: La réponse n'est pas un JSON valide
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: La fonctionnalité "Schéma utilisateur" n'est pas activée
|
NotEnabled: La fonctionnalité "Schéma utilisateur" n'est pas activée
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Esecuzione non trovata
|
NotFound: Esecuzione non trovata
|
||||||
IncludeNotFound: Includi non trovato
|
IncludeNotFound: Includi non trovato
|
||||||
NoTargets: Nessun obiettivo definito
|
NoTargets: Nessun obiettivo definito
|
||||||
|
Failed: Esecuzione fallita
|
||||||
ResponseIsNotValidJSON: La risposta non è un JSON valido
|
ResponseIsNotValidJSON: La risposta non è un JSON valido
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: La funzionalità "Schema utente" non è abilitata
|
NotEnabled: La funzionalità "Schema utente" non è abilitata
|
||||||
|
@ -553,6 +553,7 @@ Errors:
|
|||||||
NotFound: 実行が見つかりませんでした
|
NotFound: 実行が見つかりませんでした
|
||||||
IncludeNotFound: 見つからないものを含める
|
IncludeNotFound: 見つからないものを含める
|
||||||
NoTargets: ターゲットが定義されていません
|
NoTargets: ターゲットが定義されていません
|
||||||
|
Failed: 実行に失敗しました
|
||||||
ResponseIsNotValidJSON: 応答は有効な JSON ではありません
|
ResponseIsNotValidJSON: 応答は有効な JSON ではありません
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: 機能「ユーザースキーマ」が有効になっていません
|
NotEnabled: 機能「ユーザースキーマ」が有効になっていません
|
||||||
|
@ -563,6 +563,7 @@ Errors:
|
|||||||
NotFound: Извршувањето не е пронајдено
|
NotFound: Извршувањето не е пронајдено
|
||||||
IncludeNotFound: Вклучете не е пронајден
|
IncludeNotFound: Вклучете не е пронајден
|
||||||
NoTargets: Не се дефинирани цели
|
NoTargets: Не се дефинирани цели
|
||||||
|
Failed: Извршувањето не успеа
|
||||||
ResponseIsNotValidJSON: Одговорот не е валиден JSON
|
ResponseIsNotValidJSON: Одговорот не е валиден JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Функцијата „Корисничка шема“ не е овозможена
|
NotEnabled: Функцијата „Корисничка шема“ не е овозможена
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Uitvoering niet gevonden
|
NotFound: Uitvoering niet gevonden
|
||||||
IncludeNotFound: Inclusief niet gevonden
|
IncludeNotFound: Inclusief niet gevonden
|
||||||
NoTargets: Geen doelstellingen gedefinieerd
|
NoTargets: Geen doelstellingen gedefinieerd
|
||||||
|
Failed: Uitvoering mislukt
|
||||||
ResponseIsNotValidJSON: Reactie is geen geldige JSON
|
ResponseIsNotValidJSON: Reactie is geen geldige JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Functie "Gebruikersschema" is niet ingeschakeld
|
NotEnabled: Functie "Gebruikersschema" is niet ingeschakeld
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Nie znaleziono wykonania
|
NotFound: Nie znaleziono wykonania
|
||||||
IncludeNotFound: Nie znaleziono uwzględnienia
|
IncludeNotFound: Nie znaleziono uwzględnienia
|
||||||
NoTargets: Nie zdefiniowano celów
|
NoTargets: Nie zdefiniowano celów
|
||||||
|
Failed: Wykonanie nie powiodło się
|
||||||
ResponseIsNotValidJSON: Odpowiedź nie jest prawidłowym JSON-em
|
ResponseIsNotValidJSON: Odpowiedź nie jest prawidłowym JSON-em
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Funkcja „Schemat użytkownika” nie jest włączona
|
NotEnabled: Funkcja „Schemat użytkownika” nie jest włączona
|
||||||
|
@ -559,6 +559,7 @@ Errors:
|
|||||||
NotFound: Execução não encontrada
|
NotFound: Execução não encontrada
|
||||||
IncludeNotFound: Incluir não encontrado
|
IncludeNotFound: Incluir não encontrado
|
||||||
NoTargets: Nenhuma meta definida
|
NoTargets: Nenhuma meta definida
|
||||||
|
Failed: Falha na execução
|
||||||
ResponseIsNotValidJSON: A resposta não é um JSON válido
|
ResponseIsNotValidJSON: A resposta não é um JSON válido
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: O recurso "Esquema do usuário" não está habilitado
|
NotEnabled: O recurso "Esquema do usuário" não está habilitado
|
||||||
|
@ -553,6 +553,7 @@ Errors:
|
|||||||
NotFound: Исполнение не найдено
|
NotFound: Исполнение не найдено
|
||||||
IncludeNotFound: Включить не найдено
|
IncludeNotFound: Включить не найдено
|
||||||
NoTargets: Цели не определены
|
NoTargets: Цели не определены
|
||||||
|
Failed: Выполнение не удалось
|
||||||
ResponseIsNotValidJSON: Ответ не является допустимым JSON
|
ResponseIsNotValidJSON: Ответ не является допустимым JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Функция «Пользовательская схема» не включена
|
NotEnabled: Функция «Пользовательская схема» не включена
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: Exekveringen hittades inte
|
NotFound: Exekveringen hittades inte
|
||||||
IncludeNotFound: Inkluderingen hittades inte
|
IncludeNotFound: Inkluderingen hittades inte
|
||||||
NoTargets: Inga mål definierade
|
NoTargets: Inga mål definierade
|
||||||
|
Failed: Utförande misslyckades
|
||||||
ResponseIsNotValidJSON: Svaret är inte giltigt JSON
|
ResponseIsNotValidJSON: Svaret är inte giltigt JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: Funktionen "Användarschema" är inte aktiverad
|
NotEnabled: Funktionen "Användarschema" är inte aktiverad
|
||||||
|
@ -564,6 +564,7 @@ Errors:
|
|||||||
NotFound: 未找到执行
|
NotFound: 未找到执行
|
||||||
IncludeNotFound: 包括未找到的内容
|
IncludeNotFound: 包括未找到的内容
|
||||||
NoTargets: 没有定义目标
|
NoTargets: 没有定义目标
|
||||||
|
Failed: 执行失败
|
||||||
ResponseIsNotValidJSON: 响应不是有效的 JSON
|
ResponseIsNotValidJSON: 响应不是有效的 JSON
|
||||||
UserSchema:
|
UserSchema:
|
||||||
NotEnabled: 未启用“用户架构”功能
|
NotEnabled: 未启用“用户架构”功能
|
||||||
|
Loading…
x
Reference in New Issue
Block a user