add remove method for aliases
This commit is contained in:
@@ -1,92 +1,123 @@
|
||||
import type { Params, ServiceInterface } from '@feathersjs/feathers'
|
||||
import type {
|
||||
NullableId,
|
||||
Params,
|
||||
ServiceInterface,
|
||||
} from "@feathersjs/feathers";
|
||||
|
||||
import type { Application } from '../../declarations'
|
||||
import wildDuckClient from '../../clients/wildduck.client'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { BadRequest } from '@feathersjs/errors'
|
||||
import config from 'config'
|
||||
import type { Application } from "../../declarations";
|
||||
import wildDuckClient from "../../clients/wildduck.client";
|
||||
import { faker } from "@faker-js/faker";
|
||||
import { BadRequest } from "@feathersjs/errors";
|
||||
import config from "config";
|
||||
|
||||
interface Alias {
|
||||
success: boolean,
|
||||
id: string,
|
||||
address: string,
|
||||
main: boolean,
|
||||
user: string,
|
||||
tags: string[],
|
||||
created: string,
|
||||
success: boolean;
|
||||
id: string;
|
||||
address: string;
|
||||
main: boolean;
|
||||
user: string;
|
||||
tags: string[];
|
||||
created: string;
|
||||
}
|
||||
|
||||
interface GetAddressInfoResponse {
|
||||
success: boolean,
|
||||
results: Alias[]
|
||||
success: boolean;
|
||||
results: Alias[];
|
||||
}
|
||||
|
||||
interface CreateAddressResponse {
|
||||
success: boolean,
|
||||
id: string,
|
||||
success: boolean;
|
||||
id: string;
|
||||
}
|
||||
|
||||
type AliasesData = any
|
||||
type AliasesPatch = any
|
||||
type AliasesQuery = any
|
||||
type AliasesData = any;
|
||||
type AliasesPatch = any;
|
||||
type AliasesQuery = any;
|
||||
|
||||
export type { Alias as Aliases, AliasesData, AliasesPatch, AliasesQuery }
|
||||
export type { Alias as Aliases, AliasesData, AliasesPatch, AliasesQuery };
|
||||
|
||||
export interface AliasesServiceOptions {
|
||||
app: Application
|
||||
app: Application;
|
||||
}
|
||||
|
||||
export interface AliasesParams extends Params<AliasesQuery> {
|
||||
session?: any
|
||||
session?: any;
|
||||
}
|
||||
|
||||
export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
|
||||
implements ServiceInterface<Alias, AliasesData, ServiceParams, AliasesPatch>
|
||||
{
|
||||
constructor(public options: AliasesServiceOptions) { }
|
||||
constructor(public options: AliasesServiceOptions) {}
|
||||
|
||||
async find(params: ServiceParams): Promise<Alias[]> {
|
||||
const userId = await this.getUserIdByEmailAddress(params)
|
||||
const { data: userAddressesResponse } = await wildDuckClient.get<GetAddressInfoResponse>(`/users/${userId}/addresses`)
|
||||
const userId = await this.getUserIdByEmailAddress(params);
|
||||
|
||||
return userAddressesResponse.results
|
||||
return this.getUserAddresses(userId);
|
||||
}
|
||||
|
||||
async create(data: AliasesData, params: ServiceParams): Promise<Alias>
|
||||
async create(data: AliasesData, params: ServiceParams): Promise<Alias | Alias[]> {
|
||||
const userId = await this.getUserIdByEmailAddress(params)
|
||||
const aliasFirstPart = faker.animal.crocodilia()
|
||||
.replace(/\D/g, '')
|
||||
.replace(/\s/g, '')
|
||||
async create(data: AliasesData, params: ServiceParams): Promise<Alias>;
|
||||
async create(
|
||||
data: AliasesData,
|
||||
params: ServiceParams,
|
||||
): Promise<Alias | Alias[]> {
|
||||
const userId = await this.getUserIdByEmailAddress(params);
|
||||
const aliasFirstPart = faker.animal
|
||||
.crocodilia()
|
||||
.replace(/\D/g, "")
|
||||
.replace(/\s/g, "")
|
||||
.slice(0, 10);
|
||||
|
||||
const aliasSecondPart = faker.git.commitSha({ length: 5 });
|
||||
const alias = `${aliasFirstPart}-${aliasSecondPart}@${config.get('wildDuck.domain')}`;
|
||||
// const alias = `${faker.animal.crocodilia().replace(/\s/, '').slice(10)}-${faker.git.commitSha({ length: 5 })}`;
|
||||
const alias = `${aliasFirstPart}-${aliasSecondPart}@${config.get(
|
||||
"wildDuck.domain",
|
||||
)}`;
|
||||
|
||||
const createResult = await wildDuckClient.post<CreateAddressResponse>(`/users/${userId}/addresses`, {
|
||||
address: alias
|
||||
})
|
||||
const createResult = await wildDuckClient.post<CreateAddressResponse>(
|
||||
`/users/${userId}/addresses`,
|
||||
{
|
||||
address: alias,
|
||||
},
|
||||
);
|
||||
|
||||
if (!createResult.data.success) {
|
||||
throw new BadRequest('Failed to create alias')
|
||||
throw new BadRequest("Failed to create alias");
|
||||
}
|
||||
|
||||
const { data: userAddressesResponse } = await wildDuckClient.get<GetAddressInfoResponse>(`/users/${userId}/addresses`)
|
||||
|
||||
return userAddressesResponse.results
|
||||
|
||||
return this.getUserAddresses(userId);
|
||||
}
|
||||
|
||||
private async getUserIdByEmailAddress(params: ServiceParams): Promise<string> {
|
||||
private async getUserIdByEmailAddress(
|
||||
params: ServiceParams,
|
||||
): Promise<string> {
|
||||
const emails = params.session?.user?.emails;
|
||||
|
||||
const addressInfoResponse = await Promise.any(emails.map((email: string) => wildDuckClient.get<Alias>(`addresses/resolve/${email}`)))
|
||||
const addressInfoResponse = await Promise.any(
|
||||
emails.map((email: string) =>
|
||||
wildDuckClient.get<Alias>(`addresses/resolve/${email}`),
|
||||
),
|
||||
);
|
||||
|
||||
return addressInfoResponse.data.user
|
||||
return addressInfoResponse.data.user;
|
||||
}
|
||||
|
||||
private async getUserAddresses(userId: string): Promise<Alias[]> {
|
||||
const { data: userAddressesResponse } =
|
||||
await wildDuckClient.get<GetAddressInfoResponse>(
|
||||
`/users/${userId}/addresses`,
|
||||
);
|
||||
|
||||
return userAddressesResponse.results;
|
||||
}
|
||||
|
||||
async remove(id: NullableId, params: ServiceParams): Promise<Alias[]> {
|
||||
await wildDuckClient.delete<Alias>(`/addresses/${id}`);
|
||||
|
||||
const userId = await this.getUserIdByEmailAddress(params);
|
||||
|
||||
return this.getUserAddresses(userId);
|
||||
}
|
||||
}
|
||||
|
||||
export const getOptions = (app: Application) => {
|
||||
return { app }
|
||||
}
|
||||
return { app };
|
||||
};
|
||||
|
||||
@@ -1,41 +1,39 @@
|
||||
import type { Application } from '../../declarations'
|
||||
import { validateAuth } from '../../hooks/validate-auth'
|
||||
import { AliasesService, getOptions } from './aliases.class'
|
||||
import type { Application } from "../../declarations";
|
||||
import { validateAuth } from "../../hooks/validate-auth";
|
||||
import { AliasesService, getOptions } from "./aliases.class";
|
||||
|
||||
export const aliasesPath = 'aliases'
|
||||
export const aliasesMethods = ['find', 'create'] as const
|
||||
export const aliasesPath = "aliases";
|
||||
export const aliasesMethods = ["find", "create"] as const;
|
||||
|
||||
export * from './aliases.class'
|
||||
export * from "./aliases.class";
|
||||
|
||||
export const aliases = (app: Application) => {
|
||||
app.use(aliasesPath, new AliasesService(getOptions(app)), {
|
||||
methods: aliasesMethods,
|
||||
events: []
|
||||
})
|
||||
events: [],
|
||||
});
|
||||
|
||||
app.service(aliasesPath).hooks({
|
||||
around: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
before: {
|
||||
all: [
|
||||
validateAuth
|
||||
],
|
||||
all: [validateAuth],
|
||||
find: [],
|
||||
create: [],
|
||||
},
|
||||
after: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
error: {
|
||||
all: []
|
||||
}
|
||||
})
|
||||
}
|
||||
all: [],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Add this service to the service type index
|
||||
declare module '../../declarations' {
|
||||
declare module "../../declarations" {
|
||||
interface ServiceTypes {
|
||||
[aliasesPath]: AliasesService
|
||||
[aliasesPath]: AliasesService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
import type { Params, ServiceInterface } from '@feathersjs/feathers'
|
||||
import type { Params, ServiceInterface } from "@feathersjs/feathers";
|
||||
|
||||
import type { Application } from '../../declarations'
|
||||
import type { Application } from "../../declarations";
|
||||
|
||||
import { Issuer, generators } from 'openid-client'
|
||||
import config from 'config';
|
||||
import { Issuer, generators } from "openid-client";
|
||||
import config from "config";
|
||||
|
||||
type AuthOidcResponse = string;
|
||||
type AuthOidcQuery = any;
|
||||
|
||||
type AuthOidcResponse = string
|
||||
type AuthOidcQuery = any
|
||||
|
||||
export type { AuthOidcResponse as AuthOidc, AuthOidcQuery }
|
||||
export type { AuthOidcResponse as AuthOidc, AuthOidcQuery };
|
||||
|
||||
export interface AuthOidcServiceOptions {
|
||||
app: Application
|
||||
app: Application;
|
||||
}
|
||||
|
||||
export interface AuthOidcParams extends Params<AuthOidcQuery> {
|
||||
session?: any
|
||||
session?: any;
|
||||
}
|
||||
|
||||
export class AuthOidcService<ServiceParams extends AuthOidcParams = AuthOidcParams>
|
||||
implements ServiceInterface<AuthOidcResponse, ServiceParams>
|
||||
export class AuthOidcService<
|
||||
ServiceParams extends AuthOidcParams = AuthOidcParams,
|
||||
> implements ServiceInterface<AuthOidcResponse, ServiceParams>
|
||||
{
|
||||
constructor(public options: AuthOidcServiceOptions) { }
|
||||
constructor(public options: AuthOidcServiceOptions) {}
|
||||
|
||||
async find(params: ServiceParams): Promise<AuthOidcResponse> {
|
||||
const issuer = await Issuer.discover(config.get('oidc.gatewayUri'));
|
||||
const issuer = await Issuer.discover(config.get("oidc.gatewayUri"));
|
||||
const client = new issuer.Client({
|
||||
client_id: config.get('oidc.clientId'),
|
||||
client_secret: config.get('oidc.clientSecret'),
|
||||
redirect_uris: [config.get('oidc.redirectUris')],
|
||||
response_types: ['code'],
|
||||
})
|
||||
client_id: config.get("oidc.clientId"),
|
||||
client_secret: config.get("oidc.clientSecret"),
|
||||
redirect_uris: [config.get("oidc.redirectUris")],
|
||||
response_types: ["code"],
|
||||
});
|
||||
const codeVerifier = generators.codeVerifier();
|
||||
const codeChallenge = generators.codeChallenge(codeVerifier);
|
||||
|
||||
const url = client.authorizationUrl({
|
||||
redirect_uri: config.get('clientUrl') + '/auth-oidc/callback',
|
||||
scope: 'openid profile offline_access',
|
||||
response_type: 'code',
|
||||
redirect_uri: config.get("clientUrl") + "/auth-oidc/callback",
|
||||
scope: "openid profile offline_access",
|
||||
response_type: "code",
|
||||
code_challenge: codeChallenge,
|
||||
code_challenge_method: 'S256',
|
||||
code_challenge_method: "S256",
|
||||
});
|
||||
|
||||
params.session.codeVerifier = codeVerifier;
|
||||
@@ -49,5 +49,5 @@ export class AuthOidcService<ServiceParams extends AuthOidcParams = AuthOidcPara
|
||||
}
|
||||
|
||||
export const getOptions = (app: Application) => {
|
||||
return { app }
|
||||
}
|
||||
return { app };
|
||||
};
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
import type { Application } from '../../declarations'
|
||||
import { AuthOidcService, getOptions } from './auth-oidc.class'
|
||||
import type { Application } from "../../declarations";
|
||||
import { AuthOidcService, getOptions } from "./auth-oidc.class";
|
||||
|
||||
export const authOidcPath = 'auth-oidc'
|
||||
export const authOidcMethods = ['find'] as const
|
||||
export const authOidcPath = "auth-oidc";
|
||||
export const authOidcMethods = ["find"] as const;
|
||||
|
||||
export * from './auth-oidc.class'
|
||||
export * from "./auth-oidc.class";
|
||||
|
||||
export const authOidc = (app: Application) => {
|
||||
// TODO: fix this to use the correct type
|
||||
// @ts-ignore
|
||||
app.use(authOidcPath, new AuthOidcService(getOptions(app)), {
|
||||
methods: authOidcMethods,
|
||||
events: []
|
||||
}, (req: any, res: any) => {
|
||||
|
||||
return res.redirect(res.data);
|
||||
})
|
||||
app.use(
|
||||
authOidcPath,
|
||||
new AuthOidcService(getOptions(app)),
|
||||
{
|
||||
methods: authOidcMethods,
|
||||
events: [],
|
||||
},
|
||||
(req: any, res: any) => {
|
||||
return res.redirect(res.data);
|
||||
},
|
||||
);
|
||||
|
||||
app.service(authOidcPath).hooks({
|
||||
around: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
before: {
|
||||
all: [],
|
||||
find: [],
|
||||
},
|
||||
after: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
error: {
|
||||
all: []
|
||||
}
|
||||
})
|
||||
}
|
||||
all: [],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
declare module '../../declarations' {
|
||||
declare module "../../declarations" {
|
||||
interface ServiceTypes {
|
||||
[authOidcPath]: AuthOidcService
|
||||
[authOidcPath]: AuthOidcService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,68 @@
|
||||
import type { Params, ServiceInterface } from '@feathersjs/feathers'
|
||||
import type { Application } from '../../../declarations'
|
||||
import { Issuer } from 'openid-client'
|
||||
import type { Params, ServiceInterface } from "@feathersjs/feathers";
|
||||
import type { Application } from "../../../declarations";
|
||||
import { Issuer } from "openid-client";
|
||||
|
||||
import config from 'config'
|
||||
import config from "config";
|
||||
|
||||
type AuthOidcCallback = string
|
||||
type AuthOidcCallbackData = any
|
||||
type AuthOidcCallbackPatch = any
|
||||
type AuthOidcCallbackQuery = any
|
||||
type AuthOidcCallback = string;
|
||||
type AuthOidcCallbackData = any;
|
||||
type AuthOidcCallbackPatch = any;
|
||||
type AuthOidcCallbackQuery = any;
|
||||
|
||||
export type { AuthOidcCallback, AuthOidcCallbackData, AuthOidcCallbackPatch, AuthOidcCallbackQuery }
|
||||
export type {
|
||||
AuthOidcCallback,
|
||||
AuthOidcCallbackData,
|
||||
AuthOidcCallbackPatch,
|
||||
AuthOidcCallbackQuery,
|
||||
};
|
||||
|
||||
export interface AuthOidcCallbackServiceOptions {
|
||||
app: Application
|
||||
app: Application;
|
||||
}
|
||||
|
||||
export interface AuthOidcCallbackParams extends Params<AuthOidcCallbackQuery> {
|
||||
session?: any
|
||||
session?: any;
|
||||
query: {
|
||||
iss: string,
|
||||
code: string,
|
||||
}
|
||||
iss: string;
|
||||
code: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class AuthOidcCallbackService<ServiceParams extends AuthOidcCallbackParams = AuthOidcCallbackParams>
|
||||
implements ServiceInterface<AuthOidcCallback, AuthOidcCallbackData, ServiceParams, AuthOidcCallbackPatch>
|
||||
export class AuthOidcCallbackService<
|
||||
ServiceParams extends AuthOidcCallbackParams = AuthOidcCallbackParams,
|
||||
> implements
|
||||
ServiceInterface<
|
||||
AuthOidcCallback,
|
||||
AuthOidcCallbackData,
|
||||
ServiceParams,
|
||||
AuthOidcCallbackPatch
|
||||
>
|
||||
{
|
||||
constructor(public options: AuthOidcCallbackServiceOptions) { }
|
||||
constructor(public options: AuthOidcCallbackServiceOptions) {}
|
||||
|
||||
async find(params: ServiceParams): Promise<AuthOidcCallback> {
|
||||
const issuer = await Issuer.discover(config.get('oidc.gatewayUri'));
|
||||
const issuer = await Issuer.discover(config.get("oidc.gatewayUri"));
|
||||
const client = new issuer.Client({
|
||||
client_id: config.get('oidc.clientId'),
|
||||
client_secret: config.get('oidc.clientSecret'),
|
||||
redirect_uris: [config.get('oidc.redirectUris')],
|
||||
response_types: ['code'],
|
||||
})
|
||||
client_id: config.get("oidc.clientId"),
|
||||
client_secret: config.get("oidc.clientSecret"),
|
||||
redirect_uris: [config.get("oidc.redirectUris")],
|
||||
response_types: ["code"],
|
||||
});
|
||||
|
||||
const codeVerifier = params.session.codeVerifier;
|
||||
const tokenSet = await client.callback(config.get('clientUrl') + '/auth-oidc/callback', { code: params.query.code, iss: params.query.iss }, { code_verifier: codeVerifier });
|
||||
const tokenSet = await client.callback(
|
||||
config.get("clientUrl") + "/auth-oidc/callback",
|
||||
{ code: params.query.code, iss: params.query.iss },
|
||||
{ code_verifier: codeVerifier },
|
||||
);
|
||||
const userinfo = await client.userinfo(tokenSet.access_token as string);
|
||||
|
||||
params.session.user = userinfo;
|
||||
|
||||
return '/'
|
||||
return "/";
|
||||
}
|
||||
}
|
||||
|
||||
export const getOptions = (app: Application) => {
|
||||
return { app }
|
||||
}
|
||||
return { app };
|
||||
};
|
||||
|
||||
@@ -1,42 +1,49 @@
|
||||
import { http } from '@feathersjs/transport-commons'
|
||||
import type { Application } from '../../../declarations'
|
||||
import { AuthOidcCallbackService, getOptions } from './auth-oidc-callback.class'
|
||||
import { http } from "@feathersjs/transport-commons";
|
||||
import type { Application } from "../../../declarations";
|
||||
import {
|
||||
AuthOidcCallbackService,
|
||||
getOptions,
|
||||
} from "./auth-oidc-callback.class";
|
||||
|
||||
export const authOidcCallbackPath = 'auth-oidc/callback'
|
||||
export const authOidcCallbackMethods = ['find'] as const
|
||||
export const authOidcCallbackPath = "auth-oidc/callback";
|
||||
export const authOidcCallbackMethods = ["find"] as const;
|
||||
|
||||
export * from './auth-oidc-callback.class'
|
||||
export * from "./auth-oidc-callback.class";
|
||||
|
||||
export const authOidcCallback = (app: Application) => {
|
||||
// TODO: fix this to use the correct type
|
||||
// @ts-ignore
|
||||
app.use(authOidcCallbackPath, new AuthOidcCallbackService(getOptions(app)), {
|
||||
methods: authOidcCallbackMethods,
|
||||
events: []
|
||||
}, (req: any, res: any) => {
|
||||
|
||||
return res.redirect(res.data);
|
||||
})
|
||||
app.use(
|
||||
authOidcCallbackPath,
|
||||
new AuthOidcCallbackService(getOptions(app)),
|
||||
{
|
||||
methods: authOidcCallbackMethods,
|
||||
events: [],
|
||||
},
|
||||
(req: any, res: any) => {
|
||||
return res.redirect(res.data);
|
||||
},
|
||||
);
|
||||
|
||||
app.service(authOidcCallbackPath).hooks({
|
||||
around: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
before: {
|
||||
all: [],
|
||||
find: [],
|
||||
},
|
||||
after: {
|
||||
all: []
|
||||
all: [],
|
||||
},
|
||||
error: {
|
||||
all: []
|
||||
}
|
||||
})
|
||||
}
|
||||
all: [],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
declare module '../../../declarations' {
|
||||
declare module "../../../declarations" {
|
||||
interface ServiceTypes {
|
||||
[authOidcCallbackPath]: AuthOidcCallbackService
|
||||
[authOidcCallbackPath]: AuthOidcCallbackService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { authOidcCallback } from './auth-oidc/callback/auth-oidc-callback'
|
||||
import { authOidc } from './auth-oidc/auth-oidc'
|
||||
import { aliases } from './aliases/aliases'
|
||||
import type { Application } from '../declarations'
|
||||
import { authOidcCallback } from "./auth-oidc/callback/auth-oidc-callback";
|
||||
import { authOidc } from "./auth-oidc/auth-oidc";
|
||||
import { aliases } from "./aliases/aliases";
|
||||
import type { Application } from "../declarations";
|
||||
|
||||
export const services = (app: Application) => {
|
||||
app.configure(authOidcCallback)
|
||||
app.configure(authOidc)
|
||||
app.configure(aliases)
|
||||
}
|
||||
app.configure(authOidcCallback);
|
||||
app.configure(authOidc);
|
||||
app.configure(aliases);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user