ref: updated tests/prettier/lint

This commit is contained in:
montaghanmy
2023-04-04 13:51:33 +01:00
parent 1458a11e7c
commit d4b054048c
31 changed files with 259 additions and 4323 deletions
@@ -2,7 +2,6 @@ import { Channel } from "../../../../services/channels/entities/channel";
import Company from "../../../../services/user/entities/company";
import Workspace from "../../../../services/workspaces/entities/workspace";
import User from "../../../../services/user/entities/user";
import { UserObject } from "../../../../services/user/web/types";
export type EmailBuilderDataPayload = {
user: User;
@@ -55,4 +55,4 @@ export type ChannelActivityNotification = {
export interface CompanyExecutionContext extends ExecutionContext {
company: { id: string };
}
}
@@ -1,5 +1,5 @@
import { DatabaseServiceAPI } from "../../core/platform/services/database/api";
import { ConsoleOptions, ConsoleType, MergeProgress } from "./types";
import { ConsoleOptions, ConsoleType } from "./types";
import { ConsoleServiceClient } from "./client-interface";
import { ConsoleClientFactory } from "./client-factory";
import User from "../user/entities/user";
@@ -1,10 +1,8 @@
import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify";
import { authenticationSchema, consoleHookSchema, tokenRenewalSchema } from "./schemas";
import crypto from "crypto";
// import { WorkspaceBaseRequest, WorkspaceUsersBaseRequest, WorkspaceUsersRequest } from "./types";
import { ConsoleController } from "./controller";
import { ConsoleHookBody, ConsoleHookQueryString } from "../types";
import gr from "../../global-resolver";
const hookUrl = "/hook";
@@ -348,7 +348,6 @@ export const getAccessLevel = async (
repository: Repository<DriveFile>,
context: CompanyExecutionContext & { public_token?: string; twake_tab_token?: string },
): Promise<DriveFileAccessLevel | "none"> => {
if (!id || id === "root")
return !context?.user?.id ? "none" : (await isCompanyGuest(context)) ? "read" : "manage";
if (id === "trash")
@@ -800,4 +799,4 @@ export function isFileType(fileMime: string, fileName: string, requiredExtension
const secondaryExtensions = Object.keys(mimes).filter(k => mimes[k] === fileMime);
const fileExtensions = [extension, ...secondaryExtensions];
return fileExtensions.some(e => requiredExtensions.includes(e));
}
}
@@ -6,7 +6,6 @@ import { File } from "../entities/file";
import Repository from "../../../../src/core/platform/services/database/services/orm/repository/repository";
import { CompanyExecutionContext } from "../web/types";
import { logger } from "../../../core/platform/framework";
import _ from "lodash";
import { getDownloadRoute, getThumbnailRoute } from "../web/routes";
import {
CrudException,
@@ -23,9 +22,7 @@ export class FileServiceImpl {
async init(): Promise<this> {
try {
await Promise.all([
(this.repository = await gr.database.getRepository<File>("files", File)),
]);
await Promise.all([(this.repository = await gr.database.getRepository<File>("files", File))]);
} catch (err) {
logger.error("Error while initializing files service", err);
}
@@ -110,7 +107,6 @@ export class FileServiceImpl {
entity.upload_data.size = totalUploadedSize;
await this.repository.save(entity, context);
}
}
return entity;
@@ -1,261 +1,261 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
Initializable,
RealtimeDeleted,
RealtimeSaved,
TwakeContext,
TwakeServiceProvider,
} from "../../../core/platform/framework";
import { ResourcePath } from "../../../core/platform/services/realtime/types";
import {
CrudException,
DeleteResult,
ExecutionContext,
ListResult,
OperationType,
Pagination,
SaveResult,
} from "../../../core/platform/framework/api/crud-service";
import {
getUserNotificationBadgeInstance,
UserNotificationBadge,
UserNotificationBadgePrimaryKey,
UserNotificationBadgeType,
} from "../entities";
import { NotificationExecutionContext } from "../types";
import { getNotificationRoomName } from "./realtime";
import Repository from "../../../core/platform/services/database/services/orm/repository/repository";
import gr from "../../global-resolver";
import _, { pick, uniq } from "lodash";
export class UserNotificationBadgeService implements TwakeServiceProvider, Initializable {
version: "1";
repository: Repository<UserNotificationBadge>;
async init(context: TwakeContext): Promise<this> {
this.repository = await gr.database.getRepository<UserNotificationBadge>(
UserNotificationBadgeType,
UserNotificationBadge,
);
return this;
}
async get(
pk: UserNotificationBadgePrimaryKey,
context: ExecutionContext,
): Promise<UserNotificationBadge> {
return await this.repository.findOne(pk, {}, context);
}
@RealtimeSaved<UserNotificationBadge>((badge, context) => {
return [
Initializable,
RealtimeDeleted,
RealtimeSaved,
TwakeContext,
TwakeServiceProvider,
} from "../../../core/platform/framework";
import { ResourcePath } from "../../../core/platform/services/realtime/types";
import {
CrudException,
DeleteResult,
ExecutionContext,
ListResult,
OperationType,
Pagination,
SaveResult,
} from "../../../core/platform/framework/api/crud-service";
import {
getUserNotificationBadgeInstance,
UserNotificationBadge,
UserNotificationBadgePrimaryKey,
UserNotificationBadgeType,
} from "../entities";
import { NotificationExecutionContext } from "../types";
import { getNotificationRoomName } from "./realtime";
import Repository from "../../../core/platform/services/database/services/orm/repository/repository";
import gr from "../../global-resolver";
import _, { pick, uniq } from "lodash";
export class UserNotificationBadgeService implements TwakeServiceProvider, Initializable {
version: "1";
repository: Repository<UserNotificationBadge>;
async init(context: TwakeContext): Promise<this> {
this.repository = await gr.database.getRepository<UserNotificationBadge>(
UserNotificationBadgeType,
UserNotificationBadge,
);
return this;
}
async get(
pk: UserNotificationBadgePrimaryKey,
context: ExecutionContext,
): Promise<UserNotificationBadge> {
return await this.repository.findOne(pk, {}, context);
}
@RealtimeSaved<UserNotificationBadge>((badge, context) => {
return [
{
room: ResourcePath.get(getNotificationRoomName(badge.user_id)),
},
];
})
async save<SaveOptions>(
badge: UserNotificationBadge,
context: ExecutionContext,
): Promise<SaveResult<UserNotificationBadge>> {
//Initiate the digest
await gr.services.notifications.digest.putBadge(badge);
await this.repository.save(getUserNotificationBadgeInstance(badge), context);
return new SaveResult(UserNotificationBadgeType, badge, OperationType.CREATE);
}
@RealtimeDeleted<UserNotificationBadge>((badge, context) => {
return [
{
room: ResourcePath.get(getNotificationRoomName(badge.user_id)),
},
];
})
async delete(
pk: UserNotificationBadgePrimaryKey,
context?: NotificationExecutionContext,
): Promise<DeleteResult<UserNotificationBadge>> {
//Cancel the current digest as we just read the badges
await gr.services.notifications.digest.cancelDigest(pk.company_id, pk.user_id);
await this.repository.remove(pk as UserNotificationBadge, context);
return new DeleteResult(UserNotificationBadgeType, pk as UserNotificationBadge, true);
}
list(): Promise<ListResult<UserNotificationBadge>> {
throw new Error("Not implemented");
}
async listForUserPerCompanies(
user_id: string,
context: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
//We remove all badge from current company as next block will create dupicates
const companies_ids = (await gr.services.companies.getAllForUser(user_id)).map(
gu => gu.group_id,
);
let result: UserNotificationBadge[] = [];
let type = "";
for (const company_id of companies_ids) {
const find = await this.repository.find(
{
room: ResourcePath.get(getNotificationRoomName(badge.user_id)),
company_id,
user_id,
},
];
})
async save<SaveOptions>(
badge: UserNotificationBadge,
context: ExecutionContext,
): Promise<SaveResult<UserNotificationBadge>> {
//Initiate the digest
await gr.services.notifications.digest.putBadge(badge);
await this.repository.save(getUserNotificationBadgeInstance(badge), context);
return new SaveResult(UserNotificationBadgeType, badge, OperationType.CREATE);
}
@RealtimeDeleted<UserNotificationBadge>((badge, context) => {
return [
{
room: ResourcePath.get(getNotificationRoomName(badge.user_id)),
pagination: new Pagination("", "1"),
},
];
})
async delete(
pk: UserNotificationBadgePrimaryKey,
context?: NotificationExecutionContext,
): Promise<DeleteResult<UserNotificationBadge>> {
//Cancel the current digest as we just read the badges
await gr.services.notifications.digest.cancelDigest(pk.company_id, pk.user_id);
await this.repository.remove(pk as UserNotificationBadge, context);
return new DeleteResult(UserNotificationBadgeType, pk as UserNotificationBadge, true);
}
list(): Promise<ListResult<UserNotificationBadge>> {
throw new Error("Not implemented");
}
async listForUserPerCompanies(
user_id: string,
context: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
//We remove all badge from current company as next block will create dupicates
const companies_ids = (await gr.services.companies.getAllForUser(user_id)).map(
gu => gu.group_id,
);
let result: UserNotificationBadge[] = [];
let type = "";
for (const company_id of companies_ids) {
const find = await this.repository.find(
{
company_id,
user_id,
},
{
pagination: new Pagination("", "1"),
},
context,
);
type = find.type;
result = result.concat(find.getEntities());
}
const badges = new ListResult(type, result);
await this.ensureBadgesAreReachable(badges, context);
return badges;
}
async listForUser(
company_id: string,
user_id: string,
filter: Pick<UserNotificationBadgePrimaryKey, "workspace_id" | "channel_id" | "thread_id">,
context?: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
if (!company_id || !user_id) {
throw CrudException.badRequest("company_id and user_id are required");
}
//Cancel the current digest as we just read the badges
await gr.services.notifications.digest.cancelDigest(company_id, user_id);
const badges = await this.repository.find(
{
...{
company_id,
user_id,
},
...pick(filter, ["workspace_id", "channel_id", "thread_id"]),
},
{},
context,
);
await this.ensureBadgesAreReachable(badges, context);
type = find.type;
result = result.concat(find.getEntities());
}
const badges = new ListResult(type, result);
await this.ensureBadgesAreReachable(badges, context);
return badges;
}
async listForUser(
company_id: string,
user_id: string,
filter: Pick<UserNotificationBadgePrimaryKey, "workspace_id" | "channel_id" | "thread_id">,
context?: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
if (!company_id || !user_id) {
throw CrudException.badRequest("company_id and user_id are required");
}
//Cancel the current digest as we just read the badges
await gr.services.notifications.digest.cancelDigest(company_id, user_id);
const badges = await this.repository.find(
{
...{
company_id,
user_id,
},
...pick(filter, ["workspace_id", "channel_id", "thread_id"]),
},
{},
context,
);
await this.ensureBadgesAreReachable(badges, context);
return badges;
}
// This will ensure we are still in the channels and if not, we'll remove the badge
// We need to also ensure more than that
// - Are we in the workspace?
// - Are we in the company?
async ensureBadgesAreReachable(
badges: ListResult<UserNotificationBadge>,
context?: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
if (badges.getEntities().length === 0) {
return badges;
}
// This will ensure we are still in the channels and if not, we'll remove the badge
// We need to also ensure more than that
// - Are we in the workspace?
// - Are we in the company?
async ensureBadgesAreReachable(
badges: ListResult<UserNotificationBadge>,
context?: ExecutionContext,
): Promise<ListResult<UserNotificationBadge>> {
if (badges.getEntities().length === 0) {
return badges;
}
const userId = badges.getEntities()[0].user_id;
const channels = uniq(badges.getEntities().map(r => r.channel_id));
for (const channelId of channels) {
const someBadge = badges.getEntities().find(b => b.channel_id === channelId);
const channelMemberPk = {
company_id: someBadge.company_id,
workspace_id: someBadge.workspace_id,
channel_id: channelId,
user_id: userId,
};
const context = {
user: { id: channelMemberPk.user_id, server_request: true },
channel: { id: channelId, ...channelMemberPk },
};
const exists =
(await gr.services.channels.channels.get(
{
id: channelId,
..._.pick(channelMemberPk, "company_id", "workspace_id"),
},
context,
)) && (await gr.services.channels.members.get(channelMemberPk, context));
if (!exists) {
for (const badge of badges.getEntities()) {
if (badge.channel_id === channelId) this.removeUserChannelBadges(badge, context);
}
badges.filterEntities(b => b.channel_id !== channelId);
}
}
const badgePerWorkspace = _.uniqBy(badges.getEntities(), r => r.workspace_id);
for (const badge of badgePerWorkspace) {
const workspaceId = badge.workspace_id;
const companyId = badge.company_id;
if (!workspaceId || workspaceId === "direct") {
continue;
}
try {
const exists =
(await gr.services.workspaces.get({
id: workspaceId,
company_id: companyId,
})) &&
(await gr.services.workspaces.getUser({
workspaceId,
userId,
}));
if (!exists) {
await gr.services.channels.members.ensureUserNotInWorkspaceIsNotInChannel(
{ id: userId },
{ id: workspaceId, company_id: companyId },
context,
);
for (const badge of badges.getEntities()) {
if (badge.workspace_id === workspaceId) this.removeUserChannelBadges(badge, context);
}
badges.filterEntities(b => b.workspace_id !== workspaceId);
}
} catch (e) {}
}
return badges;
}
/**
* FIXME: This is a temporary implementation which is sending as many websocket notifications as there are badges to remove
* A better implementation will be to do a bulk delete and have a single websocket notification event
* @param filter
* @param context
*/
async removeUserChannelBadges(
filter: Pick<
UserNotificationBadgePrimaryKey,
"workspace_id" | "company_id" | "channel_id" | "user_id"
>,
context?: ExecutionContext,
): Promise<number> {
const badges = (
await this.repository.find(
_.pick(filter, ["workspace_id", "company_id", "channel_id", "user_id"]),
{},
const userId = badges.getEntities()[0].user_id;
const channels = uniq(badges.getEntities().map(r => r.channel_id));
for (const channelId of channels) {
const someBadge = badges.getEntities().find(b => b.channel_id === channelId);
const channelMemberPk = {
company_id: someBadge.company_id,
workspace_id: someBadge.workspace_id,
channel_id: channelId,
user_id: userId,
};
const context = {
user: { id: channelMemberPk.user_id, server_request: true },
channel: { id: channelId, ...channelMemberPk },
};
const exists =
(await gr.services.channels.channels.get(
{
id: channelId,
..._.pick(channelMemberPk, "company_id", "workspace_id"),
},
context,
)
).getEntities();
return (
await Promise.all(
badges.map(async badge => {
try {
return (await this.delete(badge)).deleted;
} catch (err) {}
}),
)
).filter(Boolean).length;
)) && (await gr.services.channels.members.get(channelMemberPk, context));
if (!exists) {
for (const badge of badges.getEntities()) {
if (badge.channel_id === channelId) this.removeUserChannelBadges(badge, context);
}
badges.filterEntities(b => b.channel_id !== channelId);
}
}
}
const badgePerWorkspace = _.uniqBy(badges.getEntities(), r => r.workspace_id);
for (const badge of badgePerWorkspace) {
const workspaceId = badge.workspace_id;
const companyId = badge.company_id;
if (!workspaceId || workspaceId === "direct") {
continue;
}
try {
const exists =
(await gr.services.workspaces.get({
id: workspaceId,
company_id: companyId,
})) &&
(await gr.services.workspaces.getUser({
workspaceId,
userId,
}));
if (!exists) {
await gr.services.channels.members.ensureUserNotInWorkspaceIsNotInChannel(
{ id: userId },
{ id: workspaceId, company_id: companyId },
context,
);
for (const badge of badges.getEntities()) {
if (badge.workspace_id === workspaceId) this.removeUserChannelBadges(badge, context);
}
badges.filterEntities(b => b.workspace_id !== workspaceId);
}
} catch (e) {}
}
return badges;
}
/**
* FIXME: This is a temporary implementation which is sending as many websocket notifications as there are badges to remove
* A better implementation will be to do a bulk delete and have a single websocket notification event
* @param filter
* @param context
*/
async removeUserChannelBadges(
filter: Pick<
UserNotificationBadgePrimaryKey,
"workspace_id" | "company_id" | "channel_id" | "user_id"
>,
context?: ExecutionContext,
): Promise<number> {
const badges = (
await this.repository.find(
_.pick(filter, ["workspace_id", "company_id", "channel_id", "user_id"]),
{},
context,
)
).getEntities();
return (
await Promise.all(
badges.map(async badge => {
try {
return (await this.delete(badge)).deleted;
} catch (err) {}
}),
)
).filter(Boolean).length;
}
}
@@ -3,7 +3,6 @@ import { Initializable, TwakeServiceProvider } from "../../../core/platform/fram
import { Paginable, Pagination } from "../../../core/platform/framework/api/crud-service";
import Repository from "../../../core/platform/services/database/services/orm/repository/repository";
import { Channel } from "../../../services/channels/entities";
import { UserObject } from "../../../services/user/web/types";
import Workspace from "../../../services/workspaces/entities/workspace";
import gr from "../../global-resolver";
import { UserNotificationBadge } from "../entities";
@@ -109,7 +108,6 @@ export class UserNotificationDigestService implements TwakeServiceProvider, Init
for (const badge of badges.getEntities()) {
if (!badge.thread_id) continue;
try {
channels[badge.channel_id] =
channels[badge.channel_id] ||
(await gr.services.channels.channels.get({
@@ -167,7 +167,7 @@ export class PushNotificationToUsersMessageProcessor
thread_id: badge.thread_id,
message_id: badge.message_id,
user_id: user,
mention_type: mentions.users.includes(user)
mention_type: mentions.users.includes(user),
});
return this.saveBadge(badgeEntity, context);
}),
@@ -83,7 +83,7 @@ export class PushReactionNotification
async buildNotificationMessageContent(
message: ReactionNotification,
): Promise<{ title: string; text: string }> {
const { company_id, workspace_id, reaction_user_id, reaction, thread_id } = message;
const { company_id, workspace_id, reaction_user_id, reaction } = message;
let title = "";
const channel: Channel = await gr.services.channels.channels.get({
@@ -102,7 +102,7 @@ export class PushReactionNotification
}),
gr.services.users.get({ id: reaction_user_id }),
]);
const companyName = company?.name || "";
const workspaceName = workspace_id === "direct" ? "Direct" : workspace?.name || "";
const userName = this.getUserName(user) || "Twake";
@@ -1,6 +1,6 @@
import { FastifyReply, FastifyRequest } from "fastify";
import { FastifyRequest } from "fastify";
import { CrudController } from "../../../../core/platform/services/webserver/types";
import { NotificationAcknowledgeBody, NotificationListQueryParameters } from "../../types";
import { NotificationListQueryParameters } from "../../types";
import {
ResourceCreateResponse,
ResourceDeleteResponse,
@@ -140,7 +140,7 @@ export class WorkspaceInviteTokensCrudController
const userId = request.currentUser.id;
const user = await gr.services.users.get({ id: userId });
let companyUser = await gr.services.companies.getCompanyUser(
const companyUser = await gr.services.companies.getCompanyUser(
{ id: company_id },
{ id: userId },
);