Skip to content

Commit

Permalink
Merge pull request #1065 from AletheiaFact/stage
Browse files Browse the repository at this point in the history
Production Release
  • Loading branch information
thesocialdev authored Oct 31, 2023
2 parents 81fe2d2 + 0e52fa8 commit d03a9ba
Show file tree
Hide file tree
Showing 170 changed files with 3,519 additions and 495 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:18.14.0-alpine AS package
FROM node:18.17.0-alpine AS package

ARG NEXT_PUBLIC_UMAMI_SITE_ID
ARG NEXT_PUBLIC_RECAPTCHA_SITEKEY
Expand Down Expand Up @@ -33,7 +33,7 @@ RUN NEXT_PUBLIC_UMAMI_SITE_ID=$NEXT_PUBLIC_UMAMI_SITE_ID \
NEXT_PUBLIC_RECAPTCHA_SITEKEY=$NEXT_PUBLIC_RECAPTCHA_SITEKEY \
yarn build

FROM node:18.14.0-alpine
FROM node:18.17.0-alpine

LABEL maintainer="Giovanni Rossini <[email protected]>"

Expand Down
51 changes: 22 additions & 29 deletions lib/editor-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class EditorParser {
}

getSourceByProperty(sources, property) {
//FIXME: Create migration
return sources.filter(
(source) => (source?.props?.field || source?.field) === property
);
Expand All @@ -47,13 +48,14 @@ export class EditorParser {
}

extractHtmlContentFromRange({ props, content }, type = "text") {
const fragmentText = content.slice(...props?.textRange);
const { textRange, targetText, sup } = props;
const fragmentText = content.slice(...textRange);
if (type === "text") {
return fragmentText;
}

if (type === "source" && fragmentText === props?.targetText) {
return `<a href='#${fragmentText}' rel='noopener noreferrer nofollow'>${fragmentText}<sup>${props?.sup}</sup></a>`;
if (type === "source" && fragmentText === targetText) {
return `<a href='#${fragmentText}' rel='noopener noreferrer nofollow'>${fragmentText}<sup>${sup}</sup></a>`;
}
return fragmentText;
}
Expand All @@ -65,19 +67,15 @@ export class EditorParser {
content
);

const htmlContent = allRanges.map(
({ targetText, textRange, sup, props, type }) => {
return this.extractHtmlContentFromRange(
{
content,
props: props
? { ...props }
: { targetText, textRange, sup },
},
type
);
}
);
const htmlContent = allRanges.map(({ props, type }) => {
return this.extractHtmlContentFromRange(
{
content,
props,
},
type
);
});

if (key === "questions") {
return htmlContent.join("");
Expand Down Expand Up @@ -285,9 +283,7 @@ export class EditorParser {
}

getRawSourcesAndSourcesRanges(sources) {
const rawSourcesRanges = sources.map(
(s) => s?.props?.textRange || s?.textRange
);
const rawSourcesRanges = sources.map(({ props }) => props.textRange);

const sourcesRanges = sources.map((source) => {
return {
Expand All @@ -306,7 +302,8 @@ export class EditorParser {
{ props, content, href = null },
type = "text"
) {
const fragmentText = content.slice(...props?.textRange);
const { textRange, targetText, id } = props;
const fragmentText = content.slice(...textRange);

switch (type) {
case "text":
Expand All @@ -315,11 +312,11 @@ export class EditorParser {
}
break;
case "source":
if (fragmentText === props?.targetText) {
if (fragmentText === targetText) {
return this.getContentObjectWithMarks(
fragmentText,
href,
props?.id
id
);
}
// Fall through to the default case if type is "source" and the text doesn't match targetText
Expand Down Expand Up @@ -403,9 +400,7 @@ export class EditorParser {
});

return [...sourcesRanges, ...missingTextRanges].sort((a, b) => {
const getRange = (item) =>
item?.textRange || item?.props?.textRange || [0];
return getRange(a)[0] - getRange(b)[0];
return a.props.textRange[0] - b.props.textRange[0];
});
}

Expand All @@ -420,12 +415,10 @@ export class EditorParser {
);

const textFragments = allRanges
.map(({ targetText, textRange, props, type, href, id = null }) => {
.map(({ props, type, href }) => {
return this.extractContentFragmentFromRange(
{
props: props
? { ...props }
: { targetText, textRange, id },
props,
content,
href,
},
Expand Down
7 changes: 7 additions & 0 deletions migrations/20231020152642-adding-name-space-property.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Db } from "mongodb";

export async function up(db: Db) {
await db
.collection("claims")
.updateMany({}, { $set: { nameSpace: "main" } });
}
28 changes: 28 additions & 0 deletions migrations/20231021165513-update-user-role-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Db } from "mongodb";

export async function up(db: Db) {
const usersCursor = await db.collection("users").find();

while (await usersCursor.hasNext()) {
const user = await usersCursor.next();

await db
.collection("users")
.updateOne(
{ _id: user._id },
{ $set: { role: { main: user.role } } }
);
}
}

export async function down(db: Db) {
const usersCursor = await db.collection("users").find();

while (await usersCursor.hasNext()) {
const user = await usersCursor.next();

await db
.collection("users")
.updateOne({ _id: user._id }, { $set: { role: user.role.main } });
}
}
3 changes: 2 additions & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"sourcesRequiredFieldError": "Source is required",
"supportEmail": "[email protected]",
"contactEmail": "[email protected]",
"captchaError": "There was an error validating the captcha"
"captchaError": "There was an error validating the captcha",
"change": "Change"
}
3 changes: 2 additions & 1 deletion public/locales/en/menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"adminItem": "Admin",
"personalityItem": "Personalities",
"claimItem": "Claims",
"kanbanItem": "Kanban"
"kanbanItem": "Kanban",
"nameSpaceItem": "Namespace"
}
8 changes: 8 additions & 0 deletions public/locales/en/namespaces.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"nameColumn": "Name",
"title": "Namespaces area",
"addNameSpace": "Add namespace",
"editNameSpace": "Edit namespace",
"nameSpaceSaved": "Namespace was saved successfully",
"selectNameSpaces": "Select the namespaces"
}
3 changes: 2 additions & 1 deletion public/locales/pt/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"sourcesRequiredFieldError": "Fonte obrigatória",
"supportEmail": "[email protected]",
"contactEmail": "[email protected]",
"captchaError": "Erro na validação do captcha"
"captchaError": "Erro na validação do captcha",
"change": "Mudar"
}
3 changes: 2 additions & 1 deletion public/locales/pt/menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"adminItem": "Admin",
"personalityItem": "Personalidades",
"claimItem": "Afirmações",
"kanbanItem": "Kanban"
"kanbanItem": "Kanban",
"nameSpaceItem": "Namespace"
}
9 changes: 9 additions & 0 deletions public/locales/pt/namespaces.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"nameColumn": "Nome",
"title": "Área de namespaces",
"addNameSpace": "Adicionar namespace",
"editNameSpace": "Editar namespace",
"nameSpaceSaved": "Namespace salvo com sucesso",
"selectNameSpaces": "Selecione os namespaces"
}

10 changes: 10 additions & 0 deletions server/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ import { EditorModule } from "./editor/editor.module";
import { BadgeModule } from "./badge/badge.module";
import { EditorParseModule } from "./editor-parse/editor-parse.module";
import { NotificationModule } from "./notifications/notifications.module";
import { CommentModule } from "./claim-review-task/comment/comment.module";
import { NameSpaceModule } from "./auth/name-space/name-space.module";
import { NameSpaceGuard } from "./auth/name-space/name-space.guard";

@Module({})
export class AppModule implements NestModule {
Expand Down Expand Up @@ -104,6 +107,8 @@ export class AppModule implements NestModule {
BadgeModule,
EditorParseModule,
NotificationModule,
CommentModule,
NameSpaceModule,
];
if (options.config.feature_flag) {
imports.push(
Expand Down Expand Up @@ -139,6 +144,11 @@ export class AppModule implements NestModule {
provide: APP_GUARD,
useExisting: SessionGuard,
},
{
provide: APP_GUARD,
useExisting: NameSpaceGuard,
},
NameSpaceGuard,
SessionGuard,
],
};
Expand Down
7 changes: 6 additions & 1 deletion server/auth/ability/abilities.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Reflector } from "@nestjs/core";
import { Configuration, FrontendApi } from "@ory/client";
import { CHECK_ABILITY, RequiredRule } from "./ability.decorator";
import { AbilityFactory } from "./ability.factory";
import { NameSpaceEnum } from "../../auth/name-space/schemas/name-space.schema";

@Injectable()
export class AbilitiesGuard implements CanActivate {
Expand All @@ -36,7 +37,11 @@ export class AbilitiesGuard implements CanActivate {
cookie: request.header("Cookie"),
});
const user = session.identity.traits;
const ability = this.caslAbilityFactor.defineAbility(user);
const nameSpaceSlug = request.params.namespace || NameSpaceEnum.Main;
const ability = this.caslAbilityFactor.defineAbility(
user,
nameSpaceSlug
);
try {
rules.forEach((rule) =>
ForbiddenError.from(ability).throwUnlessCan(
Expand Down
11 changes: 7 additions & 4 deletions server/auth/ability/ability.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,19 @@ export type AppAbility = Ability<[Action, Subjects]>;

@Injectable()
export class AbilityFactory {
defineAbility(user: User) {
defineAbility(user: User, nameSpace: string) {
const { can, cannot, build } = new AbilityBuilder(
Ability as AbilityClass<AppAbility>
);

if (user.role === Roles.Admin || user.role === Roles.SuperAdmin) {
if (
user.role[nameSpace] === Roles.Admin ||
user.role[nameSpace] === Roles.SuperAdmin
) {
can(Action.Manage, "all");
} else if (
user.role === Roles.FactChecker ||
user.role === Roles.Reviewer
user.role[nameSpace] === Roles.FactChecker ||
user.role[nameSpace] === Roles.Reviewer
) {
can(Action.Read, "all");
can(Action.Update, "all");
Expand Down
15 changes: 15 additions & 0 deletions server/auth/name-space/dto/create-namespace.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsArray, IsNotEmpty, IsOptional, IsString } from "class-validator";
import { User } from "../../../users/schemas/user.schema";

export class CreateNameSpaceDTO {
@IsString()
@IsNotEmpty()
@ApiProperty()
name: string;

@IsArray()
@IsOptional()
@ApiProperty()
users: User[];
}
10 changes: 10 additions & 0 deletions server/auth/name-space/dto/update-name-space.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PartialType } from "@nestjs/mapped-types";
import { CreateNameSpaceDTO } from "./create-namespace.dto";
import { IsString } from "class-validator";
import { ApiProperty } from "@nestjs/swagger";

export class UpdateNameSpaceDTO extends PartialType(CreateNameSpaceDTO) {
@IsString()
@ApiProperty()
_id: string;
}
65 changes: 65 additions & 0 deletions server/auth/name-space/name-space.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
Body,
Controller,
Get,
Param,
Post,
Put,
Req,
Res,
UseGuards,
} from "@nestjs/common";
import { NameSpaceService } from "./name-space.service";
import type { Request, Response } from "express";
import { ApiTags } from "@nestjs/swagger";
import { UsersService } from "../../users/users.service";
import { parse } from "url";
import { ViewService } from "../../view/view.service";
import { CreateNameSpaceDTO } from "./dto/create-namespace.dto";
import { UpdateNameSpaceDTO } from "./dto/update-name-space.dto";
import {
AdminUserAbility,
CheckAbilities,
} from "../../auth/ability/ability.decorator";
import { AbilitiesGuard } from "../../auth/ability/abilities.guard";

@Controller()
export class NameSpaceController {
constructor(
private nameSpaceService: NameSpaceService,
private usersService: UsersService,
private viewService: ViewService
) {}

@ApiTags("name-space")
@Post("api/name-space")
@UseGuards(AbilitiesGuard)
@CheckAbilities(new AdminUserAbility())
async create(@Body() namespace: CreateNameSpaceDTO) {
return await this.nameSpaceService.create(namespace);
}

@ApiTags("name-space")
@Put("api/name-space/:id")
@UseGuards(AbilitiesGuard)
@CheckAbilities(new AdminUserAbility())
async update(@Param("id") id, @Body() namespace: UpdateNameSpaceDTO) {
return await this.nameSpaceService.update(id, namespace);
}

@ApiTags("name-space")
@Get("admin/name-spaces")
public async adminNameSpaces(@Req() req: Request, @Res() res: Response) {
const nameSpaces = await this.nameSpaceService.listAll();
const users = await this.usersService.findAll({});
const parsedUrl = parse(req.url, true);
await this.viewService
.getNextServer()
.render(
req,
res,
"/admin-namespaces",
Object.assign(parsedUrl.query, { nameSpaces, users })
);
}
}
Loading

0 comments on commit d03a9ba

Please sign in to comment.