sanitize aliases response, hide delete button for non-prefereable domain aliases
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline failed

This commit is contained in:
2023-08-05 15:01:37 +03:00
parent fcb5780ef9
commit cc453e2337
5 changed files with 130 additions and 58 deletions

View File

@@ -6,11 +6,11 @@ import type {
import type { Application } from "../../declarations";
import wildDuckClient from "../../clients/wildduck.client";
import { faker } from "@faker-js/faker";
import { faker, th } from "@faker-js/faker";
import { BadRequest } from "@feathersjs/errors";
import config from "config";
interface Alias {
interface WildDuckAddress {
success: boolean;
id: string;
address: string;
@@ -20,12 +20,19 @@ interface Alias {
created: string;
}
interface GetAddressInfoResponse {
interface GetWildDuckAddressInfoResponse {
success: boolean;
results: Alias[];
results: WildDuckAddress[];
}
interface CreateAddressResponse {
interface AliasApiResponse {
id: string | null;
address: string;
tags: string[];
created: string;
}
interface CreateWildDuckAddressResponse {
success: boolean;
id: string;
}
@@ -34,7 +41,12 @@ type AliasesData = any;
type AliasesPatch = any;
type AliasesQuery = any;
export type { Alias as Aliases, AliasesData, AliasesPatch, AliasesQuery };
export type {
WildDuckAddress as Aliases,
AliasesData,
AliasesPatch,
AliasesQuery,
};
export interface AliasesServiceOptions {
app: Application;
@@ -45,21 +57,30 @@ export interface AliasesParams extends Params<AliasesQuery> {
}
export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
implements ServiceInterface<Alias, AliasesData, ServiceParams, AliasesPatch>
implements
ServiceInterface<
AliasApiResponse,
AliasesData,
ServiceParams,
AliasesPatch
>
{
constructor(public options: AliasesServiceOptions) {}
async find(params: ServiceParams): Promise<Alias[]> {
async find(params: ServiceParams): Promise<AliasApiResponse[]> {
const userId = await this.getUserIdByEmailAddress(params);
return this.getUserAddresses(userId);
}
async create(data: AliasesData, params: ServiceParams): Promise<Alias>;
async create(
data: AliasesData,
params: ServiceParams,
): Promise<Alias | Alias[]> {
): Promise<AliasApiResponse>;
async create(
data: AliasesData,
params: ServiceParams,
): Promise<AliasApiResponse | AliasApiResponse[]> {
const userId = await this.getUserIdByEmailAddress(params);
const randomString = faker.git.commitSha({ length: 4 });
@@ -73,12 +94,13 @@ export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
const emailDomain = config.get("wildDuck.domain");
const createResult = await wildDuckClient.post<CreateAddressResponse>(
`/users/${userId}/addresses`,
{
address: `${alias}@${emailDomain}`,
},
);
const createResult =
await wildDuckClient.post<CreateWildDuckAddressResponse>(
`/users/${userId}/addresses`,
{
address: `${alias}@${emailDomain}`,
},
);
if (!createResult.data.success) {
throw new BadRequest("Failed to create alias");
@@ -92,32 +114,40 @@ export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
): Promise<string> {
const emails = params.session?.user?.emails;
const preferredDomain = config.get("wildDuck.preferredDomain");
if (!emails.length || !preferredDomain) {
throw new BadRequest("Unable to find user");
}
const addressInfoResponse = await Promise.any(
emails
.filter((email: string) =>
email.endsWith(config.get("wildDuck.preferredDomain")),
)
.map((email: string) =>
wildDuckClient.get<Alias>(`addresses/resolve/${email}`),
wildDuckClient.get<WildDuckAddress>(`addresses/resolve/${email}`),
),
);
return addressInfoResponse.data.user;
}
private async getUserAddresses(userId: string): Promise<Alias[]> {
private async getUserAddresses(userId: string): Promise<AliasApiResponse[]> {
const { data: userAddressesResponse } =
await wildDuckClient.get<GetAddressInfoResponse>(
await wildDuckClient.get<GetWildDuckAddressInfoResponse>(
`/users/${userId}/addresses`,
);
return userAddressesResponse.results;
return userAddressesResponse.results.map(this.sanitizeAliasResponse);
}
async remove(id: NullableId, params: ServiceParams): Promise<Alias[]> {
const { data: addressInfoResponse } = await wildDuckClient.get<Alias>(
`addresses/resolve/${id}`,
);
async remove(
id: NullableId,
params: ServiceParams,
): Promise<AliasApiResponse[]> {
const { data: addressInfoResponse } =
await wildDuckClient.get<WildDuckAddress>(`addresses/resolve/${id}`);
const allowedDomain: string = config.get("wildDuck.domain");
// If address does not match the allowed domain, throw an error
@@ -129,10 +159,26 @@ export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
}
const userId = await this.getUserIdByEmailAddress(params);
await wildDuckClient.delete<Alias>(`users/${userId}/addresses/${id}`);
await wildDuckClient.delete<WildDuckAddress>(
`users/${userId}/addresses/${id}`,
);
return this.getUserAddresses(userId);
}
sanitizeAliasResponse(alias: WildDuckAddress): AliasApiResponse {
// Hide the id if the alias is not removable
const isRemovable =
alias.main ||
!alias.address.endsWith(config.get("wildDuck.preferredDomain"));
return {
id: isRemovable ? null : alias.id,
address: alias.address,
tags: alias.tags,
created: alias.created,
};
}
}
export const getOptions = (app: Application) => {