Update account api clients to consistently handle status code handling and return types

This commit is contained in:
Rory Powell 2023-07-18 21:14:07 +01:00
parent c5337c652a
commit 944b6e0baa
4 changed files with 140 additions and 110 deletions

View File

@ -2,127 +2,135 @@ import { Response } from "node-fetch"
import { Account, CreateAccountRequest, SearchAccountsRequest, SearchAccountsResponse } from "@budibase/types" import { Account, CreateAccountRequest, SearchAccountsRequest, SearchAccountsResponse } from "@budibase/types"
import AccountInternalAPIClient from "../AccountInternalAPIClient" import AccountInternalAPIClient from "../AccountInternalAPIClient"
import { APIRequestOpts } from "../../../types" import { APIRequestOpts } from "../../../types"
import { Header } from "@budibase/backend-core"
import BaseAPI from "./BaseAPI"
export default class AccountAPI { export default class AccountAPI extends BaseAPI {
client: AccountInternalAPIClient client: AccountInternalAPIClient
constructor(client: AccountInternalAPIClient) { constructor(client: AccountInternalAPIClient) {
super()
this.client = client this.client = client
} }
async validateEmail( async validateEmail(
email: string, email: string,
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { status: 200 }
): Promise<Response> { ) {
const [response, json] = await this.client.post( return this.doRequest(() => {
`/api/accounts/validate/email`, return this.client.post(
{ `/api/accounts/validate/email`,
body: { email }, {
} body: { email },
) }
return response )
}, opts)
} }
async validateTenantId( async validateTenantId(
tenantId: string, tenantId: string,
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { status: 200 }
): Promise<Response> { ) {
const [response, json] = await this.client.post( return this.doRequest(() => {
`/api/accounts/validate/tenantId`, return this.client.post(
{ `/api/accounts/validate/tenantId`,
body: { tenantId }, {
} body: { tenantId },
) }
return response )
}, opts)
} }
async create( async create(
body: CreateAccountRequest, body: CreateAccountRequest,
opts: APIRequestOpts & { autoVerify: boolean } = { doExpect: true, autoVerify: true } opts: APIRequestOpts & { autoVerify: boolean } = { status: 201, autoVerify: false }
): Promise<[Response, Account]> { ): Promise<[Response, Account]> {
const headers = { return this.doRequest(() => {
"no-verify": opts.autoVerify ? "1" : "0" const headers = {
} "no-verify": opts.autoVerify ? "1" : "0"
const [response, json] = await this.client.post(`/api/accounts`, {
body,
headers,
})
if (opts.doExpect) {
expect(response).toHaveStatusCode(201)
}
return [response, json]
}
async delete(accountID: string, opts: APIRequestOpts = {status:204}) {
const [response, json] = await this.client.del(
`/api/accounts/${accountID}`,
{
internal: true,
} }
) return this.client.post(`/api/accounts`, {
// can't use expect here due to use in global teardown body,
if (response.status !== opts.status) { headers,
throw new Error(`status: ${response.status} not equal to expected: ${opts.status}`) })
} }, opts)
return response
} }
async deleteCurrentAccount() { async delete(
const [response, json] = await this.client.del( accountID: string,
opts: APIRequestOpts = { status: 204 }) {
return this.doRequest(() => {
return this.client.del(
`/api/accounts/${accountID}`,
{
internal: true,
}
)
}, opts)
}
async deleteCurrentAccount(
opts: APIRequestOpts = { status: 204 }
) {
return this.doRequest(() => {
return this.client.del(
`/api/accounts` `/api/accounts`
) )
return response }, opts)
} }
async verifyAccount( async verifyAccount(
verificationCode: string, verificationCode: string,
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { status: 200 }
): Promise<Response> { ){
const [response, json] = await this.client.post( return this.doRequest(() => {
return this.client.post(
`/api/accounts/verify`, `/api/accounts/verify`,
{ {
body: { verificationCode }, body: { verificationCode },
} }
) )
if (opts.doExpect) { }, opts)
expect(response).toHaveStatusCode(200)
}
return response
} }
async verifyAccountSendEmail( async sendVerificationEmail(
email: string, email: string,
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { status: 200 }
): Promise<Response> { ): Promise<[Response, string]> {
const [response, json] = await this.client.post( return this.doRequest(async () => {
const [response] = await this.client.post(
`/api/accounts/verify/send`, `/api/accounts/verify/send`,
{ {
body: { email }, body: { email },
headers: {
[Header.RETURN_VERIFICATION_CODE]: "1"
}
} }
) )
if (opts.doExpect) { const code = response.headers.get(Header.VERIFICATION_CODE)
expect(response).toHaveStatusCode(200) return [response, code]
} }, opts)
return response
} }
async search( async search(
searchType: string, searchType: string,
search: 'email' | 'tenantId', search: 'email' | 'tenantId',
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { status: 200 }
): Promise<[Response, SearchAccountsResponse]> { ): Promise<[Response, SearchAccountsResponse]> {
let body: SearchAccountsRequest = {} return this.doRequest(() => {
let body: SearchAccountsRequest = {}
if (search === 'email') { if (search === 'email') {
body.email = searchType body.email = searchType
} else if (search === 'tenantId') { } else if (search === 'tenantId') {
body.tenantId = searchType body.tenantId = searchType
} }
return this.client.post(
const [response, json] = await this.client.post(
`/api/accounts/search`, `/api/accounts/search`,
{body: body} {
) body,
return [response, json] internal: true
}
)
}, opts)
} }
} }

View File

@ -1,32 +1,33 @@
import { Response } from "node-fetch" import { Response } from "node-fetch"
import AccountInternalAPIClient from "../AccountInternalAPIClient" import AccountInternalAPIClient from "../AccountInternalAPIClient"
import { APIRequestOpts } from "../../../types" import { APIRequestOpts } from "../../../types"
import BaseAPI from "./BaseAPI"
export default class AuthAPI { export default class AuthAPI extends BaseAPI {
client: AccountInternalAPIClient client: AccountInternalAPIClient
constructor(client: AccountInternalAPIClient) { constructor(client: AccountInternalAPIClient) {
super()
this.client = client this.client = client
} }
async login( async login(
email: string, email: string,
password: string, password: string,
opts: APIRequestOpts = { doExpect: true } opts: APIRequestOpts = { doExpect: true, status: 200 }
): Promise<[Response, string]> { ): Promise<[Response, string]> {
const [response, json] = await this.client.post( return this.doRequest(async () => {
`/api/auth/login`, const [res] = await this.client.post(
{ `/api/auth/login`,
body: { {
email: email, body: {
password: password, email: email,
}, password: password,
} },
) }
// if (opts.doExpect) { )
// expect(response).toHaveStatusCode(200) const cookie = res.headers.get("set-cookie")
// } return [res, cookie]
const cookie = response.headers.get("set-cookie") }, opts)
return [response, cookie!]
} }
} }

View File

@ -0,0 +1,22 @@
import { Response } from "node-fetch"
import { APIRequestOpts } from "../../../types"
// TODO: Add to LicenseAPI
export default class BaseAPI {
async doRequest(
request: () => Promise<[Response, any]>,
opts: APIRequestOpts): Promise<[Response, any]> {
const [response, body] = await request()
// do expect on by default
if (opts.doExpect === undefined) {
opts.doExpect = true
}
if (opts.doExpect && opts.status) {
expect(response).toHaveStatusCode(opts.status)
}
return [response, body]
}
}

View File

@ -1,31 +1,30 @@
import AccountInternalAPIClient from "../AccountInternalAPIClient" import AccountInternalAPIClient from "../AccountInternalAPIClient"
import { Account, UpdateLicenseRequest } from "@budibase/types" import { Account, UpdateLicenseRequest } from "@budibase/types"
import { Response } from "node-fetch" import { Response } from "node-fetch"
import BaseAPI from "./BaseAPI"
import { APIRequestOpts } from "../../../types"
export default class LicenseAPI { export default class LicenseAPI extends BaseAPI {
client: AccountInternalAPIClient client: AccountInternalAPIClient
constructor(client: AccountInternalAPIClient) { constructor(client: AccountInternalAPIClient) {
super()
this.client = client this.client = client
} }
async updateLicense( async updateLicense(
accountId: string, accountId: string,
body: UpdateLicenseRequest body: UpdateLicenseRequest,
opts: APIRequestOpts = { status: 200 }
): Promise<[Response, Account]> { ): Promise<[Response, Account]> {
const [response, json] = await this.client.put( return this.doRequest(() => {
`/api/accounts/${accountId}/license`, return this.client.put(
{ `/api/accounts/${accountId}/license`,
body, {
internal: true, body,
} internal: true,
) }
if (response.status !== 200) {
throw new Error(
`Could not update license for accountId=${accountId}: ${response.status}`
) )
} }, opts)
return [response, json]
} }
} }