Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Control plane #6

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions src/services/control-plane/adapters/drivens/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './logger-stub';
export * from './repo-querier-local-adapter copy';
export * from './repo-querier-stub-adapter';
7 changes: 7 additions & 0 deletions src/services/control-plane/adapters/drivens/logger-stub.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ForLogging } from "../../ports/drivens/for-logging";

export class LoggerStub implements ForLogging {
log(event: string, message: string): void {
console.log(event, message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { userManagerProxy, userPermissionManagerProxy } from "../../../repository/app/composition-root";
import { RepoUser } from "../../../repository/app/schemas";
import { Permissions } from "../../app/schemas/auth";
import { ForRepoQuerying } from "../../ports/drivens";

export class RepoQuerierStubAdapter implements ForRepoQuerying {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si es un stub no debería tener utilización real de los proxy u otros adapters. Debería de retornar un mock

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que te has equivocado con el nombre del archivo y por eso sigue diciendo que es un stub, porque es una copia del RepoQuerierStubAdapter pero ha faltado modificar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corregido!

async getUser(email: string): Promise<RepoUser> {
const user = userManagerProxy.getInternalUser(email)

return user;
}

async getPermissions(userId: string): Promise<Permissions> {
const userPermissions = await userPermissionManagerProxy.getUserPermissions(userId)

return {
admin: userPermissions.admin,
user: userPermissions.user
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { RepoUser } from "../../../repository/app/schemas";
import { UserPermissions } from "../../app/schemas/auth";
import { ForRepoQuerying } from "../../ports/drivens";

export class RepoQuerierStubAdapter implements ForRepoQuerying {
async getUser(_email: string): Promise<RepoUser> {
return {
id: "1",
name: "John Doe",
email: "[email protected]",
password: "123",
};
}

async getPermissions(_userId: string): Promise<UserPermissions> {
return Promise.resolve({ id: "1", userId: "1", admin: true, user: true });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ControlPlane } from "../../app/control-plane";
import { AuthDetails, Permissions } from "../../app/schemas/auth";
import { ForManagingAuthentication } from "../../ports/drivers";

export class AuthManagerProxyAdapter implements ForManagingAuthentication {
constructor(private readonly controlPlane: ControlPlane) {}

async getAuthDetails(email: string, password: string): Promise<AuthDetails> {
return this.controlPlane.getAuthDetails(email, password);
}

async getPermissions(userId: string): Promise<Permissions> {
return this.controlPlane.getPermissions(userId);
}
}
1 change: 1 addition & 0 deletions src/services/control-plane/adapters/drivers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './auth-manager-proxy-adapter';
15 changes: 15 additions & 0 deletions src/services/control-plane/app/composition-root.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { LoggerStub, RepoQuerierStubAdapter } from "../adapters/drivens";
import { AuthManagerProxyAdapter } from "../adapters/drivers";
import { ControlPlane } from "./control-plane";

const compositionMock = () => {
const repoQuerierstub = new RepoQuerierStubAdapter();
const loggerStub = new LoggerStub();
const controlPlane = new ControlPlane(repoQuerierstub, loggerStub);

const authManagerProxy = new AuthManagerProxyAdapter(controlPlane);

return { authManagerProxy };
};

export const { authManagerProxy } = compositionMock();
40 changes: 40 additions & 0 deletions src/services/control-plane/app/control-plane.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { beforeEach, describe, expect, it } from "vitest";
import { LoggerStub, RepoQuerierStubAdapter } from "../adapters/drivens";
import { ControlPlane } from "./control-plane";

describe("ControlPlane", () => {
const repoQuerierstub = new RepoQuerierStubAdapter();
const loggerStub = new LoggerStub();
let controlPlane = new ControlPlane(repoQuerierstub, loggerStub);

beforeEach(() => {
controlPlane = new ControlPlane(repoQuerierstub, loggerStub);
});

it.concurrent("should get auth details", async () => {
// GIVEN
const mockEmail = "[email protected]";
const mockPassword = "123";

const resultExpected = { token: "token", refreshToken: "refreshToken" };

// WHEN
const result = await controlPlane.getAuthDetails(mockEmail, mockPassword);

// THEN
expect(result).toEqual(resultExpected);
});

it.concurrent("should get permissions", async () => {
// GIVEN
const mockUserId = "1";

const resultExpected = { admin: true, user: true };

// WHEN
const result = await controlPlane.getPermissions(mockUserId);

// THEN
expect(result).toEqual(resultExpected);
});
});
43 changes: 43 additions & 0 deletions src/services/control-plane/app/control-plane.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ForLogging } from "../ports/drivens/for-logging";
import { ForRepoQuerying } from "../ports/drivens/for-repo-querying";
import { ForManagingAuthentication } from "../ports/drivers";
import { AuthDetails, Permissions } from "./schemas/auth";

export class ControlPlane implements ForManagingAuthentication {
constructor(
private readonly repoQuerier: ForRepoQuerying,
private readonly logger: ForLogging
) {}

async getAuthDetails(email: string, password: string): Promise<AuthDetails> {
const user = await this.repoQuerier.getUser(email);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

realmente esta comprobacion de si existe el user o no, se podría hacer en el repoQuerier y esto englobarlo con un try catch, cosa que si entra por el catch envie el error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tenés razón, ya lo corregí para que haga el catch del error.También vi que el logger era innecesario porque ya estaba en el repository asi que lo quité


if (!user) {
this.logger.log("GetAuthDetails", "Wrong email");
throw new Error("Wrong email");
}

if (password !== user.password) {
this.logger.log("GetAuthDetails", "Wrong password");
throw new Error("Wrong password");
}

return { token: "token", refreshToken: "refreshToken" };
}

async getPermissions(userId: string): Promise<Permissions> {
const userPermissions = await this.repoQuerier.getPermissions(userId);

if (!userPermissions) {
this.logger.log("GetPermissions", "Permissions not found");
throw new Error("Permissions not found");
}

const permissions = {
admin: userPermissions.admin,
user: userPermissions.user,
};

return permissions;
}
}
16 changes: 16 additions & 0 deletions src/services/control-plane/app/schemas/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface UserPermissions {
id: string;
userId: string;
admin: boolean;
user: boolean;
}

export interface AuthDetails {
token: string;
refreshToken: string;
}

export interface Permissions {
admin: boolean;
user: boolean;
}
3 changes: 3 additions & 0 deletions src/services/control-plane/ports/drivens/for-logging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface ForLogging {
log(event: string, message: string): void;
}
7 changes: 7 additions & 0 deletions src/services/control-plane/ports/drivens/for-repo-querying.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RepoUser } from "../../../repository/app/schemas";
import { Permissions } from "../../app/schemas/auth";

export interface ForRepoQuerying {
getUser(email: string): Promise<RepoUser>;
getPermissions(userId: string): Promise<Permissions>;
}
1 change: 1 addition & 0 deletions src/services/control-plane/ports/drivens/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./for-repo-querying";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AuthDetails, Permissions } from "../../app/schemas/auth";

export interface ForManagingAuthentication {
getAuthDetails(email: string, password: string): Promise<AuthDetails>;
getPermissions(userId: string): Promise<Permissions>;
}
1 change: 1 addition & 0 deletions src/services/control-plane/ports/drivers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./for-managing-authentication";
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class ControlAuthenticatorStub implements ForControlAuthenticating {
return Promise.resolve(authDetailsMock);
}

getPermissions(_email: string, _password: string): Promise<Permissions> {
getPermissions(_userId: string): Promise<Permissions> {
return Promise.resolve(permissionsMock);
}
}
3 changes: 2 additions & 1 deletion src/services/dashboard-api/adapters/drivens/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './control-authenticator-stub-adapter';
export * from './repo-querier-stub-adapter';
export * from './repo-querier-local-adapter';
export * from './repo-querier-stub-adapter';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { userManagerProxy } from "../../../repository/app/composition-root";
import { ExternalUser } from "../../../repository/app/schemas";
import { User } from "../../app/schemas";
import { ForRepoQuerying } from "../../ports/drivens";

export class RepoQuerierLocalAdapter implements ForRepoQuerying {
async getUser(email: string): Promise<ExternalUser> {
return await userManagerProxy.getUser(email)
}

async createUser(user: User): Promise<ExternalUser> {
return await userManagerProxy.createUser(user)
}
}
7 changes: 4 additions & 3 deletions src/services/dashboard-api/app/composition-root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
authTRPCAdapter,
} from "../adapters/drivers";
import { initTRPC } from "@trpc/server";
import { RepoQuerierLocalAdapter } from "../adapters/drivens";

const compositionMock = () => {
// DRIVENS
Expand All @@ -29,7 +30,7 @@ const compositionMock = () => {
};

export const { authenticatorProxyAdapter } = compositionMock();
/*
/*
const registerMock = {
name: "John",
email: "[email protected]",
Expand All @@ -42,12 +43,12 @@ authenticatorProxyAdapter.register(registerMock);
export const localTRPCCompose = () => {
// DRIVENS
const controlAuthenticatorStub = new ControlAuthenticatorStub();
const repoQuerierStub = new RepoQuerierStub();
const repoQuerierLocal = new RepoQuerierLocalAdapter();

// APP
const dashboardApiMock = new DashboardApi(
controlAuthenticatorStub,
repoQuerierStub
repoQuerierLocal
);

// TRPC INSTANCE
Expand Down
10 changes: 4 additions & 6 deletions src/services/dashboard-api/app/dashboard-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ export class DashboardApi implements ForAuthenticating {
email,
password
);
const permissions = await this.controlAuthenticator.getPermissions(
email,
password
);
const user = await this.repoQuerier.getUser(email);

const permissions = await this.controlAuthenticator.getPermissions(user.id);

const result = {
...user,
...authDetails,
Expand All @@ -37,8 +36,7 @@ export class DashboardApi implements ForAuthenticating {
user.password
);
const permissions = await this.controlAuthenticator.getPermissions(
user.email,
user.password
newUser.id
);

const result = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { AuthDetails, Permissions } from "../../app/schemas";

export interface ForControlAuthenticating {
getAuthDetails(email: string, password: string): Promise<AuthDetails>;
getPermissions(email: string, password: string): Promise<Permissions>;
getPermissions(userId: string): Promise<Permissions>;
}
1 change: 1 addition & 0 deletions src/services/repository/adapters/drivers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './user-manager-proxy';
export * from './user-permission-manager-proxy';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Repository } from "../../app/repository";
import { ExternalUser, User } from "../../app/schemas";
import { ExternalUser, Permissions, RepoUser, User, UserPermission } from "../../app/schemas";
import { ForManagingUser } from "../../ports/drivers";

export class UserManagerProxy implements ForManagingUser {
Expand All @@ -12,4 +12,8 @@ export class UserManagerProxy implements ForManagingUser {
async createUser(user: User): Promise<ExternalUser> {
return this.repository.createUser(user);
}

async getInternalUser(email: string): Promise<RepoUser> {
return this.repository.getInternalUser(email);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Repository } from "../../app/repository";
import { Permissions, UserPermission } from "../../app/schemas";
import { ForManagingPermission } from "../../ports/drivers/for-managing-permission";

export class UserPermissionManagerProxy implements ForManagingPermission {
constructor(private readonly repository: Repository) {}

async getUserPermissions(userId: string): Promise<UserPermission> {
return this.repository.getUserPermissions(userId)
}

async createUserPermissions(userId: string, permissions: Permissions): Promise<UserPermission> {
return this.repository.createUserPermissions(userId, permissions)
}
}
5 changes: 5 additions & 0 deletions src/services/repository/app/composition-root.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LoggerStubAdapter } from "../adapters/drivens";
import { UserPermissionManagerProxy } from "../adapters/drivers";
import { UserManagerProxy } from "./../adapters/drivers/user-manager-proxy";
import { Repository } from "./repository";

Expand All @@ -7,8 +8,12 @@ export const compositionMock = () => {
const repositoryMock = new Repository(monitorStub);

const userManagerProxy = new UserManagerProxy(repositoryMock);
const userPermissionManagerProxy = new UserPermissionManagerProxy(repositoryMock);

return {
userManagerProxy,
userPermissionManagerProxy
};
};

export const { userManagerProxy, userPermissionManagerProxy } = compositionMock();
Loading