Skip to content

Commit

Permalink
Merge branch 'main' of github.com:RezaRahemtola/Area into tom/are-412…
Browse files Browse the repository at this point in the history
…-update-darklight-web-theme
  • Loading branch information
Tomi-Tom committed Nov 5, 2023
2 parents ffefa85 + 0d177f9 commit 9932f9d
Show file tree
Hide file tree
Showing 203 changed files with 18,181 additions and 860 deletions.
36 changes: 25 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
# AREA
# Area

## Team
Area is an automation platform, available as a web app and a mobile app, that allows you to
combine Actions and REactions [from a large range of integrations]((https://rezarahemtola.notion.site/Area-Integrations-f382af642ddb49d4b5a52e3fc307bfd9)) to fit your needs.

### Frontend
You can learn more about the project [in our documentation](https://docs.area.rezar.fr) 😄

| [<img src="https://github.com/Tomi-Tom.png?size=85" width=85><br><sub>Tom BARITEAU--PETER</sub>](https://github.com/Tomi-Tom) | [<img src="https://github.com/axel-denis.png?size=85" width=85><br><sub>Axel DENIS</sub>](https://github.com/axel-denis)
|:---:| :---: |
## Getting started 🚀

### Backend
To start using our amazing platform, go to [`https://area.rezar.fr`](https://area.rezar.fr) and setup your account to start creating workflows!

| [<img src="https://github.com/Croos3r.png?size=85" width=85><br><sub>Dorian MOY</sub>](https://github.com/Croos3r) | [<img src="https://github.com/EdenComp.png?size=85" width=85><br><sub>Florian LAUCH</sub>](https://github.com/EdenComp)
|:---:| :---: |
If you want a more detailed guide of the different options to use Area (including self-hosted 💻), [check this page](https://docs.area.rezar.fr/#/general/getting-started).

### Full-stack & Project manager
| [<img src="https://github.com/RezaRahemtola.png?size=85" width=85><br><sub>Reza Rahemtola</sub>](https://github.com/RezaRahemtola)
| :---: |
## How it works 🤔

If you're here for the technical details, we got you covered too!
You can dive into the architecture documentation explaining how we are using [microservices](https://docs.area.rezar.fr/#/architecture/workers)
and a [supervisor](https://docs.area.rezar.fr/#/architecture/supervisor) to create Docker containers on-demand.

> 💡 Some pretty standard parts may not be covered, but don't hesitate to reach out by creating an issue on [our repository](https://github.com/RezaRahemtola/Area), we'll be happy to help you!
## Contribute 🤝

If you want to go a step forward and participate in the development of features to enhance Area, we'd be glad to onboard you 🥇

Reach out to [`[email protected]`](mailto:[email protected]) and we'll get back to you in a few business days!

## Team ❤️

| [<img src="https://github.com/Croos3r.png?size=85" width=85><br><sub>Dorian MOY</sub>](https://github.com/Croos3r)<br><sub>Backend</sub> | [<img src="https://github.com/EdenComp.png?size=85" width=85><br><sub>Florian LAUCH</sub>](https://github.com/EdenComp)<br><sub>Microservices</sub> | [<img src="https://github.com/Tomi-Tom.png?size=85" width=85><br><sub>Tom BARITEAU-PETER</sub>](https://github.com/Tomi-Tom)<br><sub>Mobile</sub> | [<img src="https://github.com/axel-denis.png?size=85" width=85><br><sub>Axel DENIS</sub>](https://github.com/axel-denis)<br><sub>Mobile</sub> | [<img src="https://github.com/RezaRahemtola.png?size=85" width=85><br><sub>Reza RAHEMTOLA</sub>](https://github.com/RezaRahemtola)<br><sub>Web & DevOps</sub>
|:---:| :---: | :---: | :---: | :---: |
2 changes: 2 additions & 0 deletions backend/back/src/connections/connections.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import { OauthController } from "./oauth.controller";
import { OauthService } from "./oauth.service";
import { UsersModule } from "../users/users.module";
import { AuthModule } from "../auth/auth.module";
import { GrpcModule } from "../grpc/grpc.module";

@Module({
imports: [
TypeOrmModule.forFeature([UserConnection, ServiceScope]),
forwardRef(() => ServicesModule),
HttpModule,
UsersModule,
forwardRef(() => GrpcModule),
forwardRef(() => AuthModule),
],
controllers: [ConnectionsController, OauthController],
Expand Down
12 changes: 12 additions & 0 deletions backend/back/src/connections/oauth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
Controller,
ForbiddenException,
forwardRef,
Get,
Inject,
InternalServerErrorException,
Logger,
Param,
Expand All @@ -17,6 +19,7 @@ import { ServiceIdParamDto } from "../param-validators.dto";
import { ConnectionsService } from "./connections.service";
import { AuthService } from "../auth/auth.service";
import { UsersService } from "../users/users.service";
import { GrpcService } from "../grpc/grpc.service";

@ApiTags("OAuth Callbacks")
@Controller("connections/oauth")
Expand All @@ -29,6 +32,8 @@ export class OauthController {
private readonly connectionService: ConnectionsService,
private readonly authService: AuthService,
private readonly usersService: UsersService,
@Inject(forwardRef(() => GrpcService))
private readonly grpcService: GrpcService,
) {}

@Get("/:serviceId/callback")
Expand Down Expand Up @@ -66,6 +71,13 @@ export class OauthController {
const connection = await this.connectionService.createUserConnection(userId, serviceId, scopes, data);
if (!connection) throw new InternalServerErrorException("Failed to create connection");
this.logger.log(`Connection created for user ${userId}, redirecting to frontend...`);
await this.grpcService.onAction({
name: "area-on-account-connect",
identifier: `area-on-account-connect-${userId}`,
params: {
service: serviceId,
},
});
}
return response.redirect(
`${this.configService.getOrThrow<string>("FRONT_OAUTH_REDIRECTION_URL")}?${queryParams.toString()}`,
Expand Down
8 changes: 8 additions & 0 deletions backend/back/src/connections/oauth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -604,5 +604,13 @@ export class OauthService {
throw new Error("Cannot create OAuth connection for riot service");
},
},
area: {
urlFactory: () => {
throw new Error("Cannot create OAuth URL for area service");
},
connectionFactory: () => {
throw new Error("Cannot create OAuth connection for area service");
},
},
};
}
28 changes: 28 additions & 0 deletions backend/back/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ import ActivityLog from "./activity/entities/activity-log.entity";
import { AddActivityLogEntity1698986590525 } from "./migrations/1698986590525-AddActivityLogEntity";
import { CreateRiotGamesService1698964479750 } from "./services/seed/1698964479750-CreateRiotGamesService";
import { CreateRiotGamesActions1698964479850 } from "./workflows/seed/1698964479850-CreateRiotGamesActions";
import { CreateTodoistCreateTaskReaction1699101589099 } from "./workflows/seed/1699101589099-CreateTodoistCreateTaskReaction";
import { CreateAirtableDeleteRecordReaction1699107944021 } from "./workflows/seed/1699107944021-CreateAirtableDeleteRecordReaction";
import { CreateTwitterCreateTweetReaction1699115775099 } from "./workflows/seed/1699115775099-CreateTwitterCreateTweetReaction";
import { ChangeRiotLogoToSvg1699116526789 } from "./services/seed/1699116526789-ChangeRiotLogoToSvg";
import { CreateOutlookSendEmailReaction1699126617355 } from "./workflows/seed/1699126617355-CreateOutlookSendEmailReaction";
import { CreateSlackCreateMessageReaction1699131357051 } from "./workflows/seed/1699131357051-CreateSlackCreateMessageReaction";
import { CreateDiscordOnGuildJoinAction1699140593736 } from "./workflows/seed/1699140593736-CreateDiscordOnGuildJoinAction";
import { CreateTodoistTaskReactions1699140054686 } from "./workflows/seed/1699140054686-CreateTodoistTaskReactions";
import { CreateAreaService1699143731594 } from "./services/seed/1699143731594-CreateAreaService";
import { CreateAreaOnActionAction1699145276143 } from "./workflows/seed/1699145276143-CreateAreaOnActionAction";
import { CreateDiscordNewActions1699165196600 } from "./workflows/seed/1699165196600-CreateDiscordNewActions";
import { CreateAreaAreas1699152935342 } from "./workflows/seed/1699152935342-CreateAreaAreas";
import { FixAddScopeToLinearOnIssueCreate1699190007820 } from "./workflows/seed/1699190007820-FixAddScopeToLinearOnIssueCreate";
import { CreateLinearProjectCommentAREAs1699202040386 } from "./workflows/seed/1699202040386-CreateLinearProjectCommentAREAs";

dotenv.config();

Expand Down Expand Up @@ -153,6 +167,20 @@ export const DATA_SOURCE_OPTIONS: DataSourceOptions = {
AddActivityLogEntity1698986590525,
CreateRiotGamesService1698964479750,
CreateRiotGamesActions1698964479850,
CreateTodoistCreateTaskReaction1699101589099,
CreateAirtableDeleteRecordReaction1699107944021,
CreateTwitterCreateTweetReaction1699115775099,
ChangeRiotLogoToSvg1699116526789,
CreateOutlookSendEmailReaction1699126617355,
CreateSlackCreateMessageReaction1699131357051,
CreateDiscordOnGuildJoinAction1699140593736,
CreateTodoistTaskReactions1699140054686,
CreateAreaService1699143731594,
CreateAreaOnActionAction1699145276143,
CreateDiscordNewActions1699165196600,
CreateAreaAreas1699152935342,
FixAddScopeToLinearOnIssueCreate1699190007820,
CreateLinearProjectCommentAREAs1699202040386,
],
synchronize: process.env.NODE_ENV === "development",
};
Expand Down
4 changes: 2 additions & 2 deletions backend/back/src/grpc/grpc.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Controller } from "@nestjs/common";
import { GrpcMethod } from "@nestjs/microservices";
import { ApiExcludeController } from "@nestjs/swagger";
import { JobData } from "./grpc.dto";
import { JobData, JobError } from "./grpc.dto";
import { GrpcService } from "./grpc.service";

@ApiExcludeController()
Expand All @@ -20,7 +20,7 @@ export class GrpcController {
}

@GrpcMethod("AreaBackService", "OnError")
async onError(data: JobData): Promise<void> {
async onError(data: JobError): Promise<void> {
await this.grpcService.onError(data);
}
}
22 changes: 15 additions & 7 deletions backend/back/src/grpc/grpc.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { forwardRef, Inject, Injectable, Logger, OnModuleInit } from "@nestjs/common";
import { ClientGrpc } from "@nestjs/microservices";
import { AuthenticatedJobData, GrpcResponse, JobData, JobId, JobList } from "./grpc.dto";
import { AuthenticatedJobData, GrpcResponse, JobData, JobError, JobId, JobList } from "./grpc.dto";
import { firstValueFrom, Observable } from "rxjs";
import { JobsParams, JobsType } from "../types/jobs";
import { JobsIdentifiers } from "../types/jobIds";
Expand Down Expand Up @@ -35,11 +35,7 @@ export class GrpcService implements OnModuleInit {
await this.jobsService.synchronizeJobs();
}

launchJob<TJob extends JobsType, TParams extends JobsParams["mappings"][TJob]>(
name: TJob,
params: TParams,
auth: unknown,
): Promise<GrpcResponse> {
launchJob<TJob extends JobsType>(name: TJob, params: JobsParams[TJob], auth: unknown): Promise<GrpcResponse> {
const identifier = JobsIdentifiers[name](params);
this.logger.log(
`Launching job ${identifier} with name ${name} and params ${JSON.stringify({
Expand Down Expand Up @@ -79,6 +75,18 @@ export class GrpcService implements OnModuleInit {
this.logger.log(`Received action job data ${JSON.stringify(data, undefined, 2)}`);
await this.activityService.createActivityLogsForJobIdentifier("ran", data.identifier);
await this.jobsService.launchNextJob(data);

if (data.name === "area-on-action") return;
const owners = await this.jobsService.getWorkflowOwnersForAction(data.identifier);
for (const owner of owners) {
await this.onAction({
name: "area-on-action",
identifier: `area-on-action-${owner}`,
params: {
name: data.name,
},
});
}
}

async onReaction(data: JobData) {
Expand All @@ -87,7 +95,7 @@ export class GrpcService implements OnModuleInit {
await this.jobsService.launchNextJob(data);
}

async onError(data: JobData) {
async onError(data: JobError) {
this.logger.error(`Received error job data ${JSON.stringify(data, undefined, 2)}`);
await this.activityService.createActivityLogsForJobIdentifier("error", data.identifier);
}
Expand Down
52 changes: 52 additions & 0 deletions backend/back/src/jobs/back-jobs.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { forwardRef, Inject, Injectable } from "@nestjs/common";
import { JobData } from "../grpc/grpc.dto";
import { JobsType } from "../types/jobs";
import { JobsService } from "./jobs.service";
import { WorkflowToggleParams } from "../types/jobParams";
import { WorkflowsService } from "../workflows/workflows.service";
import { GrpcService } from "../grpc/grpc.service";
import { JobsIdentifiers } from "../types/jobIds";

@Injectable()
export class BackJobsService {
constructor(
@Inject(forwardRef(() => GrpcService)) private readonly grpcService: GrpcService,
@Inject(forwardRef(() => JobsService)) private readonly jobsService: JobsService,
private readonly workflowsService: WorkflowsService,
) {}

async toggleWorkflow(params: WorkflowToggleParams, newState: boolean) {
const jobName = `area-${newState ? "enable" : "disable"}-workflow`;
const workflow = await this.workflowsService.getWorkflowByNameAndOwner(params.workflowName, params.ownerId);

if (workflow.active === newState) return;
try {
await this.workflowsService.toggleWorkflow(workflow.id, newState, params.ownerId);
await this.grpcService.onAction({
name: jobName,
identifier: `area-${newState ? "enable" : "disable"}-workflow-${params.ownerId}`,
params: {},
});
} catch (e) {
await this.grpcService.onError({
identifier: JobsIdentifiers[jobName](params),
error: e.message,
isAuthError: false,
});
}
}

async executeBackJob(job: JobData) {
const jobType: JobsType = job.name as JobsType;
const params = await this.jobsService.convertParams(jobType, job.params);

switch (jobType) {
case "area-disable-workflow":
await this.toggleWorkflow(params as WorkflowToggleParams, false);
break;
case "area-enable-workflow":
await this.toggleWorkflow(params as WorkflowToggleParams, true);
break;
}
}
}
16 changes: 16 additions & 0 deletions backend/back/src/jobs/jobs.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { JobsType } from "../types/jobs";

export const AREAS_WITHOUT_GRPC: JobsType[] = [
"area-disable-workflow",
"area-enable-workflow",
"area-on-account-connect",
"area-on-action",
"area-on-workflow-create",
"area-on-workflow-toggle",
"facebook-on-status-create",
"linear-on-comment-create",
"linear-on-issue-create",
"linear-on-issue-update",
"linear-on-project-create",
"linear-on-project-update",
];
3 changes: 2 additions & 1 deletion backend/back/src/jobs/jobs.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { WorkflowsModule } from "../workflows/workflows.module";
import { TypeOrmModule } from "@nestjs/typeorm";
import WorkflowArea from "../workflows/entities/workflow-area.entity";
import { ConnectionsModule } from "../connections/connections.module";
import { BackJobsService } from "./back-jobs.service";

@Module({
imports: [
Expand All @@ -14,7 +15,7 @@ import { ConnectionsModule } from "../connections/connections.module";
forwardRef(() => GrpcModule),
],
controllers: [],
providers: [JobsService],
providers: [BackJobsService, JobsService],
exports: [JobsService],
})
export class JobsModule {}
Loading

0 comments on commit 9932f9d

Please sign in to comment.