Fix token auth native (#558)

* Fix token auth on Native

* Fix pre-release action
This commit is contained in:
Reckless_Satoshi 2023-05-06 13:42:48 +00:00 committed by GitHub
parent daa1127cfc
commit 25f0b0eea5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 135 additions and 146 deletions

View File

@ -15,6 +15,7 @@ on:
jobs: jobs:
build-android: build-android:
permissions: write-all
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@ -65,7 +66,7 @@ jobs:
# Create artifacts (only for Release) # Create artifacts (only for Release)
# Create app-universal-release APK artifact asset for Release # Create app-universal-release APK artifact asset for Release
- name: 'Upload universal .apk Release Artifact (for Release)' - name: 'Upload universal .apk Release Artifact (for Release)'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
if: inputs.semver != '' # If this workflow is called from release.yml if: inputs.semver != '' # If this workflow is called from release.yml
with: with:
name: robosats-${{ inputs.semver }}-universal.apk name: robosats-${{ inputs.semver }}-universal.apk
@ -73,7 +74,7 @@ jobs:
# Create app-arm64-v8a-release APK artifact asset for Release # Create app-arm64-v8a-release APK artifact asset for Release
- name: 'Upload arm64-v8a .apk Release Artifact (for Release)' - name: 'Upload arm64-v8a .apk Release Artifact (for Release)'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
if: inputs.semver != '' # If this workflow is called from release.yml if: inputs.semver != '' # If this workflow is called from release.yml
with: with:
name: robosats-${{ inputs.semver }}-arm64-v8a.apk name: robosats-${{ inputs.semver }}-arm64-v8a.apk
@ -81,7 +82,7 @@ jobs:
# Create app-armeabi-v7a-release APK artifact asset for Release # Create app-armeabi-v7a-release APK artifact asset for Release
- name: 'Upload armeabi-v7a .apk Release Artifact (for Release)' - name: 'Upload armeabi-v7a .apk Release Artifact (for Release)'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
if: inputs.semver != '' # If this workflow is called from release.yml if: inputs.semver != '' # If this workflow is called from release.yml
with: with:
name: robosats-${{ inputs.semver }}-armeabi-v7a.apk name: robosats-${{ inputs.semver }}-armeabi-v7a.apk
@ -89,7 +90,7 @@ jobs:
# Create app-x86_64-release APK artifact asset for Release # Create app-x86_64-release APK artifact asset for Release
- name: 'Upload x86_64 .apk Release Artifact (for Release)' - name: 'Upload x86_64 .apk Release Artifact (for Release)'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
if: inputs.semver != '' # If this workflow is called from release.yml if: inputs.semver != '' # If this workflow is called from release.yml
with: with:
name: robosats-${{ inputs.semver }}-x86_64.apk name: robosats-${{ inputs.semver }}-x86_64.apk
@ -97,7 +98,7 @@ jobs:
# Create app-x86-release APK artifact asset for Release # Create app-x86-release APK artifact asset for Release
- name: 'Upload x86 .apk Release Artifact (for Release)' - name: 'Upload x86 .apk Release Artifact (for Release)'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
if: inputs.semver != '' # If this workflow is called from release.yml if: inputs.semver != '' # If this workflow is called from release.yml
with: with:
name: robosats-${{ inputs.semver }}-x86.apk name: robosats-${{ inputs.semver }}-x86.apk
@ -106,14 +107,10 @@ jobs:
- name: 'Create Pre-release' - name: 'Create Pre-release'
id: create_release id: create_release
if: inputs.semver == '' # only if this workflow is not called from a push to tag (a Release) if: inputs.semver == '' # only if this workflow is not called from a push to tag (a Release)
uses: actions/create-release@v1 uses: ncipollo/release-action@v1.12.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: android-${{ steps.commit.outputs.short }} tag: android-${{ steps.commit.outputs.short }}
release_name: robosats-android-${{ steps.commit.outputs.short }} name: robosats-android-${{ steps.commit.outputs.short }}
changelog: mobile/CHANGELOG.md
draft: false
prerelease: true prerelease: true
# Upload universal APK to pre-release # Upload universal APK to pre-release

View File

@ -49,17 +49,17 @@ jobs:
cd frontend cd frontend
npm run build npm run build
- name: 'Archive Web Basic Build Results' - name: 'Archive Web Basic Build Results'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
with: with:
name: web-main-js name: web-main-js
path: frontend/static/frontend/main.js path: frontend/static/frontend/main.js
- name: 'Archive Web PRO Build Results' - name: 'Archive Web PRO Build Results'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
with: with:
name: web-pro-js name: web-pro-js
path: frontend/static/frontend/pro.js path: frontend/static/frontend/pro.js
- name: 'Archive Mobile Build Results' - name: 'Archive Mobile Build Results'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3.1.2
with: with:
name: mobile-web.bundle name: mobile-web.bundle
path: mobile/html/Web.bundle path: mobile/html/Web.bundle

View File

@ -67,21 +67,15 @@ jobs:
semver: ${{ needs.check-versions.outputs.semver }} semver: ${{ needs.check-versions.outputs.semver }}
release: release:
permissions: write-all
needs: [check-versions, coordinator-image, client-image, android-build] needs: [check-versions, coordinator-image, client-image, android-build]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: "Generate Release Changelog"
id: changelog
uses: heinrichreimer/github-changelog-generator-action@v2.3
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Release - name: Release
id: create-release id: create-release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with:
body: ${{ steps.changelog.outputs.changelog }}
# Upload app-universal-release APK artifact asset # Upload app-universal-release APK artifact asset
- name: 'Download universal APK Artifact' - name: 'Download universal APK Artifact'

View File

@ -956,7 +956,7 @@ class HistoricalViewSchema:
class StealthViewSchema: class StealthViewSchema:
put = { post = {
"summary": "Update stealth option", "summary": "Update stealth option",
"description": "Update stealth invoice option for the user", "description": "Update stealth invoice option for the user",
"responses": { "responses": {

View File

@ -15,7 +15,7 @@ from rest_framework.authentication import (
SessionAuthentication, # DEPRECATE session authentication SessionAuthentication, # DEPRECATE session authentication
) )
from rest_framework.authentication import TokenAuthentication from rest_framework.authentication import TokenAuthentication
from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView from rest_framework.generics import CreateAPIView, ListAPIView
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
@ -1094,14 +1094,14 @@ class HistoricalView(ListAPIView):
return Response(payload, status.HTTP_200_OK) return Response(payload, status.HTTP_200_OK)
class StealthView(UpdateAPIView): class StealthView(APIView):
authentication_classes = [TokenAuthentication, SessionAuthentication] authentication_classes = [TokenAuthentication, SessionAuthentication]
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
serializer_class = StealthSerializer serializer_class = StealthSerializer
@extend_schema(**StealthViewSchema.put) @extend_schema(**StealthViewSchema.post)
def put(self, request): def post(self, request):
serializer = self.serializer_class(data=request.data) serializer = self.serializer_class(data=request.data)
if not serializer.is_valid(): if not serializer.is_valid():

View File

@ -58,13 +58,15 @@ const OrderPage = (): JSX.Element => {
escrow_duration: order.escrow_duration, escrow_duration: order.escrow_duration,
bond_size: order.bond_size, bond_size: order.bond_size,
}; };
apiClient.post(baseUrl, '/api/make/', body, robot.tokenSHA256).then((data: any) => { apiClient
if (data.bad_request) { .post(baseUrl, '/api/make/', body, { tokenSHA256: robot.tokenSHA256 })
setBadOrder(data.bad_request); .then((data: any) => {
} else if (data.id) { if (data.bad_request) {
navigate('/order/' + data.id); setBadOrder(data.bad_request);
} } else if (data.id) {
}); navigate('/order/' + data.id);
}
});
} }
}; };

View File

@ -30,17 +30,13 @@ import { EnableTelegramDialog } from '.';
import BoltIcon from '@mui/icons-material/Bolt'; import BoltIcon from '@mui/icons-material/Bolt';
import SendIcon from '@mui/icons-material/Send'; import SendIcon from '@mui/icons-material/Send';
import NumbersIcon from '@mui/icons-material/Numbers'; import NumbersIcon from '@mui/icons-material/Numbers';
import ContentCopy from '@mui/icons-material/ContentCopy';
import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents'; import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import { UserNinjaIcon } from '../Icons'; import { UserNinjaIcon } from '../Icons';
import { systemClient } from '../../services/System';
import { getHost, getWebln } from '../../utils'; import { getHost, getWebln } from '../../utils';
import RobotAvatar from '../RobotAvatar'; import RobotAvatar from '../RobotAvatar';
import { apiClient } from '../../services/api'; import { apiClient } from '../../services/api';
import { Robot } from '../../models'; import { Robot } from '../../models';
import { Page } from '../../basic/NavBar';
interface Props { interface Props {
open: boolean; open: boolean;
@ -96,7 +92,7 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
{ {
invoice: rewardInvoice, invoice: rewardInvoice,
}, },
robot.tokenSHA256, { tokenSHA256: robot.tokenSHA256 },
) )
.then((data: any) => { .then((data: any) => {
setBadInvoice(data.bad_invoice ?? ''); setBadInvoice(data.bad_invoice ?? '');
@ -110,7 +106,7 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
const setStealthInvoice = (wantsStealth: boolean) => { const setStealthInvoice = (wantsStealth: boolean) => {
apiClient apiClient
.put(baseUrl, '/api/stealth/', { wantsStealth }, robot.tokenSHA256) .post(baseUrl, '/api/stealth/', { wantsStealth }, { tokenSHA256: robot.tokenSHA256 })
.then((data) => setRobot({ ...robot, stealthInvoices: data?.wantsStealth })); .then((data) => setRobot({ ...robot, stealthInvoices: data?.wantsStealth }));
}; };

View File

@ -249,13 +249,15 @@ const MakerForm = ({
escrow_duration: maker.escrowDuration, escrow_duration: maker.escrowDuration,
bond_size: maker.bondSize, bond_size: maker.bondSize,
}; };
apiClient.post(baseUrl, '/api/make/', body, robot.tokenSHA256).then((data: object) => { apiClient
setBadRequest(data.bad_request); .post(baseUrl, '/api/make/', body, { tokenSHA256: robot.tokenSHA256 })
if (data.id) { .then((data: object) => {
onOrderCreated(data.id); setBadRequest(data.bad_request);
} if (data.id) {
setSubmittingRequest(false); onOrderCreated(data.id);
}); }
setSubmittingRequest(false);
});
} }
setOpenDialogs(false); setOpenDialogs(false);
}; };

View File

@ -285,7 +285,7 @@ const TakeButton = ({ order, setOrder, baseUrl, info }: TakeButtonProps): JSX.El
action: 'take', action: 'take',
amount: order.currency == 1000 ? takeAmount / 100000000 : takeAmount, amount: order.currency == 1000 ? takeAmount / 100000000 : takeAmount,
}, },
robot.tokenSHA256, { tokenSHA256: robot.tokenSHA256 },
) )
.then((data) => { .then((data) => {
setLoadingTake(false); setLoadingTake(false);

View File

@ -76,7 +76,9 @@ const EncryptedTurtleChat: React.FC<Props> = ({
const loadMessages: () => void = () => { const loadMessages: () => void = () => {
apiClient apiClient
.get(baseUrl, `/api/chat/?order_id=${orderId}&offset=${lastIndex}`, robot.tokenSHA256) .get(baseUrl, `/api/chat/?order_id=${orderId}&offset=${lastIndex}`, {
tokenSHA256: robot.tokenSHA256,
})
.then((results: any) => { .then((results: any) => {
if (results) { if (results) {
setPeerConnected(results.peer_connected); setPeerConnected(results.peer_connected);
@ -175,7 +177,7 @@ const EncryptedTurtleChat: React.FC<Props> = ({
order_id: orderId, order_id: orderId,
offset: lastIndex, offset: lastIndex,
}, },
robot.tokenSHA256, { tokenSHA256: robot.tokenSHA256 },
) )
.then((response) => { .then((response) => {
if (response != null) { if (response != null) {

View File

@ -173,7 +173,7 @@ const TradeBox = ({
statement, statement,
rating, rating,
}, },
robot.tokenSHA256, { tokenSHA256: robot.tokenSHA256 },
) )
.catch(() => { .catch(() => {
setOpen(closeAll); setOpen(closeAll);

View File

@ -296,7 +296,7 @@ export const useAppStore = () => {
const fetchOrder = function () { const fetchOrder = function () {
if (currentOrder != undefined) { if (currentOrder != undefined) {
apiClient apiClient
.get(baseUrl, '/api/order/?order_id=' + currentOrder, robot.tokenSHA256) .get(baseUrl, '/api/order/?order_id=' + currentOrder, { tokenSHA256: robot.tokenSHA256 })
.then(orderReceived); .then(orderReceived);
} }
}; };
@ -325,9 +325,14 @@ export const useAppStore = () => {
const encPrivKey = newKeys?.encPrivKey ?? robot.encPrivKey ?? ''; const encPrivKey = newKeys?.encPrivKey ?? robot.encPrivKey ?? '';
const pubKey = newKeys?.pubKey ?? robot.pubKey ?? ''; const pubKey = newKeys?.pubKey ?? robot.pubKey ?? '';
// On first authenticated request, pubkey and privkey must be in header cookies // On first authenticated requests, pubkey and privkey are needed in header cookies
systemClient.setCookie('public_key', pubKey.split('\n').join('\\')); const auth = {
systemClient.setCookie('encrypted_private_key', encPrivKey.split('\n').join('\\')); tokenSHA256,
keys: {
pubKey: pubKey.split('\n').join('\\'),
encPrivKey: encPrivKey.split('\n').join('\\'),
},
};
if (!isRefresh) { if (!isRefresh) {
setRobot((robot) => { setRobot((robot) => {
@ -340,7 +345,7 @@ export const useAppStore = () => {
} }
apiClient apiClient
.get(baseUrl, '/api/robot/', tokenSHA256) .get(baseUrl, '/api/robot/', auth)
.then((data: any) => { .then((data: any) => {
const newRobot = { const newRobot = {
avatarLoaded: isRefresh ? robot.avatarLoaded : false, avatarLoaded: isRefresh ? robot.avatarLoaded : false,

View File

@ -2,7 +2,7 @@ class Robot {
constructor(garageRobot?: Robot) { constructor(garageRobot?: Robot) {
if (garageRobot != null) { if (garageRobot != null) {
this.token = garageRobot?.token ?? undefined; this.token = garageRobot?.token ?? undefined;
this.tokenSHA256 = garageRobot?.tokenSHA256 ?? undefined; this.tokenSHA256 = garageRobot?.tokenSHA256 ?? '';
this.pubKey = garageRobot?.pubKey ?? undefined; this.pubKey = garageRobot?.pubKey ?? undefined;
this.encPrivKey = garageRobot?.encPrivKey ?? undefined; this.encPrivKey = garageRobot?.encPrivKey ?? undefined;
} }
@ -12,7 +12,7 @@ class Robot {
public token?: string; public token?: string;
public bitsEntropy?: number; public bitsEntropy?: number;
public shannonEntropy?: number; public shannonEntropy?: number;
public tokenSHA256?: string; public tokenSHA256: string = '';
public pubKey?: string; public pubKey?: string;
public encPrivKey?: string; public encPrivKey?: string;
public stealthInvoices: boolean = true; public stealthInvoices: boolean = true;

View File

@ -1,32 +1,29 @@
import { ApiClient } from '../api'; import { ApiClient, Auth } from '..';
import { systemClient } from '../../System'; import { systemClient } from '../../System';
class ApiNativeClient implements ApiClient { class ApiNativeClient implements ApiClient {
private assetsCache: { [path: string]: string } = {}; private assetsCache: { [path: string]: string } = {};
private assetsPromises: { [path: string]: Promise<string | undefined> } = {}; private assetsPromises: { [path: string]: Promise<string | undefined> } = {};
private readonly getHeaders: (tokenSHA256?: string) => HeadersInit = (tokenSHA256) => { private readonly getHeaders: (auth?: Auth) => HeadersInit = (auth) => {
let headers = { let headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}; };
if (tokenSHA256) { if (auth) {
headers = { headers = {
...headers, ...headers,
...{ ...{
Authorization: `Token ${tokenSHA256}`, Authorization: `Token ${auth.tokenSHA256}`,
}, },
}; };
} }
const encrypted_private_key = systemClient.getCookie('encrypted_private_key'); if (auth?.keys) {
const public_key = systemClient.getCookie('public_key');
if (encrypted_private_key && public_key) {
headers = { headers = {
...headers, ...headers,
...{ ...{
Cookie: `public_key=${public_key};encrypted_private_key=${encrypted_private_key}`, Cookie: `public_key=${auth.keys.pubKey};encrypted_private_key=${auth.keys.encPrivKey}`,
}, },
}; };
} }
@ -52,46 +49,46 @@ class ApiNativeClient implements ApiClient {
return await new Promise((res, _rej) => res({})); return await new Promise((res, _rej) => res({}));
}; };
public delete: ( public delete: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined> =
baseUrl: string, async (baseUrl, path, auth) => {
path: string, return await window.NativeRobosats?.postMessage({
tokenSHA256?: string, category: 'http',
) => Promise<object | undefined> = async (baseUrl, path, tokenSHA256) => { type: 'delete',
return await window.NativeRobosats?.postMessage({ baseUrl,
category: 'http', path,
type: 'delete', headers: this.getHeaders(auth),
baseUrl, }).then(this.parseResponse);
path, };
headers: this.getHeaders(tokenSHA256),
}).then(this.parseResponse);
};
public post: ( public post: (
baseUrl: string, baseUrl: string,
path: string, path: string,
body: object, body: object,
tokenSHA256?: string, auth?: Auth,
) => Promise<object | undefined> = async (baseUrl, path, body, tokenSHA256) => { ) => Promise<object | undefined> = async (baseUrl, path, body, auth) => {
return await window.NativeRobosats?.postMessage({ return await window.NativeRobosats?.postMessage({
category: 'http', category: 'http',
type: 'post', type: 'post',
baseUrl, baseUrl,
path, path,
body, body,
headers: this.getHeaders(tokenSHA256), headers: this.getHeaders(auth),
}).then(this.parseResponse); }).then(this.parseResponse);
}; };
public get: (baseUrl: string, path: string, tokenSHA256?: string) => Promise<object | undefined> = public get: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined> = async (
async (baseUrl, path, tokenSHA256) => { baseUrl,
return await window.NativeRobosats?.postMessage({ path,
category: 'http', auth,
type: 'get', ) => {
baseUrl, return await window.NativeRobosats?.postMessage({
path, category: 'http',
headers: this.getHeaders(tokenSHA256), type: 'get',
}).then(this.parseResponse); baseUrl,
}; path,
headers: this.getHeaders(auth),
}).then(this.parseResponse);
};
public fileImageUrl: (baseUrl: string, path: string) => Promise<string | undefined> = async ( public fileImageUrl: (baseUrl: string, path: string) => Promise<string | undefined> = async (
baseUrl, baseUrl,

View File

@ -1,76 +1,75 @@
import { ApiClient } from '..'; import { ApiClient, Auth } from '..';
import { systemClient } from '../../System';
class ApiWebClient implements ApiClient { class ApiWebClient implements ApiClient {
private readonly getHeaders: (tokenSHA256?: string) => HeadersInit = (tokenSHA256) => { private readonly getHeaders: (auth?: Auth) => HeadersInit = (auth) => {
let headers = { let headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}; };
if (tokenSHA256) { if (auth) {
headers = { headers = {
...headers, ...headers,
...{ ...{
Authorization: `Token ${tokenSHA256}`, Authorization: `Token ${auth.tokenSHA256}`,
}, },
}; };
} }
// set cookies before sending the request
if (auth?.keys) {
systemClient.setCookie('public_key', auth.keys.pubKey);
systemClient.setCookie('encrypted_private_key', auth.keys.encPrivKey);
}
return headers; return headers;
}; };
public post: ( public post: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise<object> =
baseUrl: string, async (baseUrl, path, body, auth) => {
path: string, const requestOptions = {
body: object, method: 'POST',
tokenSHA256?: string, headers: this.getHeaders(auth),
) => Promise<object> = async (baseUrl, path, body, tokenSHA256) => { body: JSON.stringify(body),
const requestOptions = { };
method: 'POST',
headers: this.getHeaders(tokenSHA256), return await fetch(baseUrl + path, requestOptions).then(
body: JSON.stringify(body), async (response) => await response.json(),
);
}; };
return await fetch(baseUrl + path, requestOptions).then( public put: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise<object> =
async (response) => await response.json(), async (baseUrl, path, body, auth) => {
); const requestOptions = {
}; method: 'PUT',
headers: this.getHeaders(auth),
public put: ( body: JSON.stringify(body),
baseUrl: string, };
path: string, return await fetch(baseUrl + path, requestOptions).then(
body: object, async (response) => await response.json(),
tokenSHA256?: string, );
) => Promise<object> = async (baseUrl, path, body, tokenSHA256) => {
const requestOptions = {
method: 'PUT',
headers: this.getHeaders(tokenSHA256),
body: JSON.stringify(body),
}; };
return await fetch(baseUrl + path, requestOptions).then(
async (response) => await response.json(),
);
};
public delete: (baseUrl: string, path: string, tokenSHA256?: string) => Promise<object> = async ( public delete: (baseUrl: string, path: string, auth?: Auth) => Promise<object> = async (
baseUrl, baseUrl,
path, path,
tokenSHA256, auth,
) => { ) => {
const requestOptions = { const requestOptions = {
method: 'DELETE', method: 'DELETE',
headers: this.getHeaders(tokenSHA256), headers: this.getHeaders(auth),
}; };
return await fetch(baseUrl + path, requestOptions).then( return await fetch(baseUrl + path, requestOptions).then(
async (response) => await response.json(), async (response) => await response.json(),
); );
}; };
public get: (baseUrl: string, path: string, tokenSHA256?: string) => Promise<object> = async ( public get: (baseUrl: string, path: string, auth?: Auth) => Promise<object> = async (
baseUrl, baseUrl,
path, path,
tokenSHA256, auth,
) => { ) => {
return await fetch(baseUrl + path, { headers: this.getHeaders(tokenSHA256) }).then( return await fetch(baseUrl + path, { headers: this.getHeaders(auth) }).then(
async (response) => await response.json(), async (response) => await response.json(),
); );
}; };

View File

@ -1,21 +1,16 @@
import ApiWebClient from './ApiWebClient'; import ApiWebClient from './ApiWebClient';
import ApiNativeClient from './ApiNativeClient'; import ApiNativeClient from './ApiNativeClient';
export interface Auth {
tokenSHA256: string;
keys?: { pubKey: string; encPrivKey: string };
}
export interface ApiClient { export interface ApiClient {
post: ( post: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise<object | undefined>;
baseUrl: string, put: (baseUrl: string, path: string, body: object, auth?: Auth) => Promise<object | undefined>;
path: string, get: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined>;
body: object, delete: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined>;
tokenSHA256?: string,
) => Promise<object | undefined>;
put: (
baseUrl: string,
path: string,
body: object,
tokenSHA256?: string,
) => Promise<object | undefined>;
get: (baseUrl: string, path: string, tokenSHA256?: string) => Promise<object | undefined>;
delete: (baseUrl: string, path: string, tokenSHA256?: string) => Promise<object | undefined>;
fileImageUrl?: (baseUrl: string, path: string) => Promise<string | undefined>; fileImageUrl?: (baseUrl: string, path: string) => Promise<string | undefined>;
} }