add merchant instances/auth test case
This commit is contained in:
parent
98ab998a1e
commit
81be4aacd8
@ -94,6 +94,7 @@ import {
|
||||
TippingReserveStatus,
|
||||
TipCreateConfirmation,
|
||||
TipCreateRequest,
|
||||
MerchantInstancesResponse,
|
||||
} from "./merchantApiTypes";
|
||||
import { ApplyRefundResponse } from "@gnu-taler/taler-wallet-core";
|
||||
import { PendingOperationsResponse } from "@gnu-taler/taler-wallet-core";
|
||||
@ -1171,6 +1172,40 @@ export interface MerchantServiceInterface {
|
||||
readonly name: string;
|
||||
}
|
||||
|
||||
export class MerchantApiClient {
|
||||
constructor(
|
||||
private baseUrl: string,
|
||||
private auth: MerchantAuthConfiguration,
|
||||
) {}
|
||||
|
||||
async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
|
||||
const baseUrl = this.baseUrl;
|
||||
const url = new URL("private/auth", baseUrl);
|
||||
await axios.post(url.href, auth, {
|
||||
headers: this.makeAuthHeader(),
|
||||
});
|
||||
}
|
||||
|
||||
async getInstances(): Promise<MerchantInstancesResponse> {
|
||||
const url = new URL("private/instances", this.baseUrl);
|
||||
const resp = await axios.get(url.href, {
|
||||
headers: this.makeAuthHeader(),
|
||||
});
|
||||
return resp.data;
|
||||
}
|
||||
|
||||
makeAuthHeader(): Record<string, string> {
|
||||
switch (this.auth.method) {
|
||||
case "external":
|
||||
return {};
|
||||
case "token":
|
||||
return {
|
||||
Authorization: `Bearer ${this.auth.token}`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace MerchantPrivateApi {
|
||||
export async function createOrder(
|
||||
merchantService: MerchantServiceInterface,
|
||||
@ -1407,8 +1442,9 @@ export class MerchantService implements MerchantServiceInterface {
|
||||
}
|
||||
console.log("adding instance");
|
||||
const url = `http://localhost:${this.merchantConfig.httpPort}/private/instances`;
|
||||
const auth = instanceConfig.auth ?? { method: "external" };
|
||||
await axios.post(url, {
|
||||
auth: { method: "external" },
|
||||
auth,
|
||||
payto_uris: instanceConfig.paytoUris,
|
||||
id: instanceConfig.id,
|
||||
name: instanceConfig.name,
|
||||
@ -1443,8 +1479,13 @@ export class MerchantService implements MerchantServiceInterface {
|
||||
}
|
||||
}
|
||||
|
||||
export interface MerchantAuthConfiguration {
|
||||
method: "external" | "token";
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export interface MerchantInstanceConfig {
|
||||
authToken?: string;
|
||||
auth?: MerchantAuthConfiguration;
|
||||
id: string;
|
||||
name: string;
|
||||
paytoUris: string[];
|
||||
|
@ -40,6 +40,7 @@ import {
|
||||
AmountString,
|
||||
Timestamp,
|
||||
CoinPublicKeyString,
|
||||
EddsaPublicKeyString,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import { codecForAmountString } from "@gnu-taler/taler-wallet-core/lib/util/amounts";
|
||||
|
||||
@ -294,3 +295,25 @@ export interface TipCreateRequest {
|
||||
// will be included in the tip_token.
|
||||
next_url: string;
|
||||
}
|
||||
|
||||
|
||||
export interface MerchantInstancesResponse {
|
||||
// List of instances that are present in the backend (see Instance)
|
||||
instances: MerchantInstanceDetail[];
|
||||
}
|
||||
|
||||
export interface MerchantInstanceDetail {
|
||||
// Merchant name corresponding to this instance.
|
||||
name: string;
|
||||
|
||||
// Merchant instance this response is about ($INSTANCE)
|
||||
id: string;
|
||||
|
||||
// Public key of the merchant/instance, in Crockford Base32 encoding.
|
||||
merchant_pub: EddsaPublicKeyString;
|
||||
|
||||
// List of the payment targets supported by this instance. Clients can
|
||||
// specify the desired payment target in /order requests. Note that
|
||||
// front-ends do not have to support wallets selecting payment targets.
|
||||
payment_targets: string[];
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
This file is part of GNU Taler
|
||||
(C) 2021 Taler Systems S.A.
|
||||
|
||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import { URL } from "@gnu-taler/taler-wallet-core";
|
||||
import axios from "axios";
|
||||
import {
|
||||
ExchangeService,
|
||||
GlobalTestState,
|
||||
MerchantApiClient,
|
||||
MerchantService,
|
||||
setupDb,
|
||||
} from "./harness";
|
||||
|
||||
/**
|
||||
* Do basic checks on instance management and authentication.
|
||||
*/
|
||||
export async function runMerchantInstancesTest(t: GlobalTestState) {
|
||||
// Set up test environment
|
||||
|
||||
const db = await setupDb(t);
|
||||
|
||||
const exchange = ExchangeService.create(t, {
|
||||
name: "testexchange-1",
|
||||
currency: "TESTKUDOS",
|
||||
httpPort: 8081,
|
||||
database: db.connStr,
|
||||
});
|
||||
|
||||
const merchant = await MerchantService.create(t, {
|
||||
name: "testmerchant-1",
|
||||
currency: "TESTKUDOS",
|
||||
httpPort: 8083,
|
||||
database: db.connStr,
|
||||
});
|
||||
|
||||
// We add the exchange to the config, but note that the exchange won't be started.
|
||||
merchant.addExchange(exchange);
|
||||
|
||||
await merchant.start();
|
||||
await merchant.pingUntilAvailable();
|
||||
|
||||
// Base URL for the default instance.
|
||||
const baseUrl = merchant.makeInstanceBaseUrl();
|
||||
|
||||
{
|
||||
const r = await axios.get(new URL("config", baseUrl).href);
|
||||
console.log(r.data);
|
||||
t.assertDeepEqual(r.data.currency, "TESTKUDOS");
|
||||
}
|
||||
|
||||
// Instances should initially be empty
|
||||
{
|
||||
const r = await axios.get(new URL("private/instances", baseUrl).href);
|
||||
t.assertDeepEqual(r.data.instances, []);
|
||||
}
|
||||
|
||||
// Add an instance, no auth!
|
||||
await merchant.addInstance({
|
||||
id: "default",
|
||||
name: "Default Instance",
|
||||
paytoUris: [`payto://x-taler-bank/merchant-default`],
|
||||
auth: {
|
||||
method: "external",
|
||||
},
|
||||
});
|
||||
|
||||
let merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
|
||||
method: "external",
|
||||
});
|
||||
|
||||
{
|
||||
const r = await merchantClient.getInstances();
|
||||
t.assertDeepEqual(r.instances.length, 1);
|
||||
}
|
||||
|
||||
// Check that a "malformed" bearer Authorization header gets ignored
|
||||
{
|
||||
const url = merchant.makeInstanceBaseUrl();
|
||||
const resp = await axios.get(new URL("private/instances", url).href, {
|
||||
headers: {
|
||||
"Authorization": "foo bar-baz",
|
||||
},
|
||||
});
|
||||
t.assertDeepEqual(resp.status, 200);
|
||||
}
|
||||
|
||||
await merchantClient.changeAuth({
|
||||
method: "token",
|
||||
token: "secret-token:foobar",
|
||||
});
|
||||
|
||||
// Now this should fail, as we didn't change the auth of the client yet.
|
||||
const exc = await t.assertThrowsAsync(async () => {
|
||||
await merchantClient.getInstances();
|
||||
});
|
||||
|
||||
t.assertAxiosError(exc);
|
||||
t.assertAxiosError(exc.response?.status === 401);
|
||||
|
||||
merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
|
||||
method: "token",
|
||||
token: "secret-token:foobar",
|
||||
});
|
||||
|
||||
// With the new client auth settings, request should work again.
|
||||
await merchantClient.getInstances();
|
||||
|
||||
// Now, try some variations.
|
||||
|
||||
{
|
||||
const url = merchant.makeInstanceBaseUrl();
|
||||
const resp = await axios.get(new URL("private/instances", url).href, {
|
||||
headers: {
|
||||
// Note the spaces
|
||||
"Authorization": "Bearer secret-token:foobar",
|
||||
}
|
||||
});
|
||||
t.assertDeepEqual(resp.status, 200);
|
||||
}
|
||||
}
|
||||
|
||||
runMerchantInstancesTest.suites = ["merchant"];
|
@ -59,6 +59,7 @@ import { runLibeufinRefundTest } from "./test-libeufin-refund";
|
||||
import { runLibeufinTutorialTest } from "./test-libeufin-tutorial";
|
||||
import { runDepositTest } from "./test-deposit";
|
||||
import CancellationToken from "cancellationtoken";
|
||||
import { runMerchantInstancesTest } from "./test-merchant-instances";
|
||||
|
||||
/**
|
||||
* Test runner.
|
||||
@ -83,6 +84,7 @@ const allTests: TestMainFunction[] = [
|
||||
runLibeufinTutorialTest,
|
||||
runLibeufinRefundTest,
|
||||
runMerchantExchangeConfusionTest,
|
||||
runMerchantInstancesTest,
|
||||
runMerchantLongpollingTest,
|
||||
runMerchantRefundApiTest,
|
||||
runPayAbortTest,
|
||||
|
Loading…
Reference in New Issue
Block a user