Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions modules/authentication/src/Authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,12 @@ export default class Authentication extends ManagedModule<Config> {
const { email, teamId } = call.request;

try {
const deletedToken = await Token.getInstance().deleteOne({
// @ts-expect-error Unsafe nested property access
const invitationQuery: Indexable = {
'data.teamId': teamId,
'data.email': email,
});
};

const deletedToken = await Token.getInstance().deleteOne(invitationQuery);

if (deletedToken.deletedCount === 0) {
return callback({
Expand Down
22 changes: 13 additions & 9 deletions modules/authentication/src/handlers/metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ConduitRouteActions,
ConduitRouteReturnDefinition,
GrpcError,
Indexable,
ParsedRouterRequest,
UnparsedRouterResponse,
} from '@conduitplatform/grpc-sdk';
Expand Down Expand Up @@ -70,10 +71,11 @@ export class MetamaskHandlers implements IAuthenticationStrategy {
const { ethPublicAddress } = call.request.params;
const normalizedEthPublicAddress = ethPublicAddress.toLowerCase();

const existingUser: User | null = await User.getInstance().findOne({
// @ts-expect-error Unsafe nested property access
const metamaskQuery: Indexable = {
'metamask.ethPublicAddress': normalizedEthPublicAddress,
});
};

const existingUser: User | null = await User.getInstance().findOne(metamaskQuery);

if (existingUser) {
return { nonce: existingUser.metamask!.nonce };
Expand All @@ -100,10 +102,11 @@ export class MetamaskHandlers implements IAuthenticationStrategy {
throw new GrpcError(status.UNAUTHENTICATED, 'No headers provided');
}

const user = await User.getInstance().findOne({
// @ts-expect-error Unsafe nested property access
const metamaskQuery: Indexable = {
'metamask.ethPublicAddress': normalizedEthPublicAddress,
});
};

const user = await User.getInstance().findOne(metamaskQuery);

if (isNil(user)) {
throw new GrpcError(
Expand Down Expand Up @@ -145,10 +148,11 @@ export class MetamaskHandlers implements IAuthenticationStrategy {
);
}

await User.getInstance().findByIdAndUpdate(user._id, {
// @ts-expect-error Unsafe nested property access
const nonceUpdate: Indexable = {
'metamask.nonce': uuid(),
});
};

await User.getInstance().findByIdAndUpdate(user._id, nonceUpdate);

ConduitGrpcSdk.Metrics?.increment('logged_in_users_total');
const config = ConfigController.getInstance().config;
Expand Down
34 changes: 17 additions & 17 deletions modules/authentication/src/handlers/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,12 @@ export class TeamsHandler implements IAuthenticationStrategy {
}

async getUserInvites(call: ParsedRouterRequest): Promise<UnparsedRouterResponse> {
const invites = await Token.getInstance().findMany({
const userInvitesQuery: Indexable = {
tokenType: TokenType.TEAM_INVITE_TOKEN,
// @ts-ignore
'data.email': call.request.context.user.email,
});
};

const invites = await Token.getInstance().findMany(userInvitesQuery);
return {
invites: invites.map(invite => ({
teamId: invite.data.teamId,
Expand Down Expand Up @@ -579,12 +580,13 @@ export class TeamsHandler implements IAuthenticationStrategy {
}

// Delete any existing invite for the same email and team
await Token.getInstance().deleteOne({
const existingInviteQuery: Indexable = {
tokenType: TokenType.TEAM_INVITE_TOKEN,
// @ts-expect-error Unsafe nested property access
'data.teamId': teamId,
'data.email': email,
});
};

await Token.getInstance().deleteOne(existingInviteQuery);

const invitation = await this.createUserInvitation({
teamId,
Expand Down Expand Up @@ -645,12 +647,13 @@ export class TeamsHandler implements IAuthenticationStrategy {
}

// Delete any existing invite for the same email and team
await Token.getInstance().deleteOne({
const invitationQuery: Indexable = {
tokenType: TokenType.TEAM_INVITE_TOKEN,
// @ts-expect-error Unsafe nested property access
'data.teamId': teamId,
'data.email': email,
});
};

await Token.getInstance().deleteOne(invitationQuery);

return 'OK';
}
Expand Down Expand Up @@ -682,17 +685,14 @@ export class TeamsHandler implements IAuthenticationStrategy {
);
}

const invites = await Token.getInstance().findMany({
const teamInvitesQuery: Indexable = {
tokenType: TokenType.TEAM_INVITE_TOKEN,
// @ts-expect-error Unsafe nested property access
'data.teamId': teamId,
});
};

const count = await Token.getInstance().countDocuments({
tokenType: TokenType.TEAM_INVITE_TOKEN,
// @ts-expect-error Unsafe nested property access
'data.teamId': teamId,
});
const invites = await Token.getInstance().findMany(teamInvitesQuery);

const count = await Token.getInstance().countDocuments(teamInvitesQuery);

return {
invites,
Expand Down
27 changes: 20 additions & 7 deletions modules/database/src/adapters/DatabaseAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,16 +472,29 @@ export abstract class DatabaseAdapter<T extends Schema> {
canModify: 'Everything',
canDelete: true,
} as const;

const setDefaultPermission = <K extends keyof typeof defaultPermissions>(
permissions: NonNullable<
NonNullable<ConduitSchema['modelOptions']['conduit']>['permissions']
>,
key: K,
) => {
if (!Object.prototype.hasOwnProperty.call(permissions, key)) {
permissions[key] = defaultPermissions[key];
}
};

if (isNil(schema.modelOptions.conduit)) schema.modelOptions.conduit = {};

if (isNil(schema.modelOptions.conduit.permissions)) {
schema.modelOptions.conduit!.permissions = defaultPermissions;
schema.modelOptions.conduit.permissions = { ...defaultPermissions };
} else {
Object.keys(defaultPermissions).forEach(perm => {
if (!schema.modelOptions.conduit!.permissions!.hasOwnProperty(perm)) {
// @ts-ignore
schema.modelOptions.conduit!.permissions![perm] =
defaultPermissions[perm as keyof typeof defaultPermissions];
}
const permissions = schema.modelOptions.conduit.permissions;
const defaultPermissionKeys = Object.keys(defaultPermissions) as Array<
keyof typeof defaultPermissions
>;
defaultPermissionKeys.forEach(perm => {
setDefaultPermission(permissions, perm);
});
}
return schema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,8 @@ export function extractFieldProperties(
} else if (objectField.hasOwnProperty('unique') && objectField.unique) {
res.unique = objectField.unique ?? false;
res.allowNull = false;
} else if (objectField.hasOwnProperty('required') && objectField.required) {
// @ts-expect-error
res.allowNull = !objectField.required ?? true;
} else if (objectField.hasOwnProperty('required') && isBoolean(objectField.required)) {
res.allowNull = !objectField.required;
}

return res;
Expand Down
22 changes: 14 additions & 8 deletions modules/database/src/utils/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,22 +199,28 @@ function validateCrudOperations(crudOperations: CrudOperations) {
throw new Error(`CMS field 'crudOperations' must be of type Object`);

Object.keys(crudOperations).forEach(op => {
if (!allowedCrudOperations.includes(op as keyof CrudOperations)) {
const crudOperation = op as keyof CrudOperations;

if (!allowedCrudOperations.includes(crudOperation)) {
throw new Error(`Unrecognized CRUD operation '${op}' provided`);
}
// @ts-ignore
if (!isObject(crudOperations[op])) {

const operationConfig = crudOperations[crudOperation];

if (!isObject(operationConfig)) {
throw new Error(`Crud operation field '${op}' must be of type Object`);
}
// @ts-ignore
Object.keys(crudOperations[op]).forEach(opField => {
if (!['enabled', 'authenticated'].includes(opField)) {

Object.keys(operationConfig).forEach(opField => {
const crudOperationField = opField as keyof typeof operationConfig;

if (!['enabled', 'authenticated'].includes(crudOperationField)) {
throw new Error(
`Unrecognized crud operation field '${opField}' for operation '${op}' provided`,
);
}
// @ts-ignore
if (!isBoolean(crudOperations[op][opField])) {

if (!isBoolean(operationConfig[crudOperationField])) {
throw new Error(
`Crud operation field '${opField}' for operation '${op}' must be of type Boolean`,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { getHandleBarsValues } from '../../utils/index.js';
import { UpdateEmailTemplate } from '../../interfaces/UpdateEmailTemplate.js';
import { MandrillTemplate } from '../../interfaces/mandrill/MandrillTemplate.js';

// @ts-expect-error
// missing typings for nodemailer-mandrill-transport
import mandrillTransport from 'nodemailer-mandrill-transport';
import { Indexable } from '@conduitplatform/grpc-sdk';

Expand Down
13 changes: 13 additions & 0 deletions modules/email/src/types/nodemailer-mandrill-transport.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
declare module 'nodemailer-mandrill-transport' {
import type { Transport } from 'nodemailer';

interface MandrillTransportOptions {
auth: {
apiKey: string;
};
}

function mandrillTransport(options: MandrillTransportOptions): Transport;

export default mandrillTransport;
}
22 changes: 15 additions & 7 deletions modules/storage/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,25 @@ import { randomUUID } from 'node:crypto';
import { ConfigController } from '@conduitplatform/module-tools';
import { status } from '@grpc/grpc-js';

export async function streamToBuffer(readableStream: any): Promise<Buffer> {
return new Promise((resolve, reject) => {
export async function streamToBuffer(
readableStream?: NodeJS.ReadableStream,
): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => {
if (!readableStream) {
reject(new Error('Readable stream is undefined'));
return;
}

const chunks: Buffer[] = [];
readableStream.on('data', (data: any) => {
chunks.push(data instanceof Buffer ? data : Buffer.from(data));

readableStream.on('data', (data: string | Buffer | Uint8Array) => {
chunks.push(Buffer.isBuffer(data) ? data : Buffer.from(data));
});

readableStream.on('end', () => {
// shouldn't really provide an error
// @ts-expect-error
resolve(Buffer.concat(chunks));
resolve(Buffer.concat(chunks as unknown as readonly Uint8Array[]));
});

readableStream.on('error', reject);
});
}
Expand Down
Loading