Skip to content

Commit

Permalink
[PM-14417] Create admin TaskService (#12891)
Browse files Browse the repository at this point in the history
* [PM-14416] Add initial SecurityTask models and enums

* [PM-14416] Add support for PATCH request method and 204 No Content response

* [PM-14416] Add initial task service abstraction

* [PM-14416] Add SecurityTask state/key definitions

* [PM-14416] Add DefaultTaskService implementation

* [PM-14416] Add DefaultTaskService tests

* [PM-14416] Add better null checking to new models

* [PM-14416] Improve null value filtering for task service

* initial commit, added absract file and implementation file

* Added abstract method and implemented bulk create method

* Implemented get all api

* created spec file

* Fixed references

* Added exports

* Added tests

* fixed suggestions

* fixed test

---------

Co-authored-by: Shane Melton <[email protected]>
  • Loading branch information
gbubemismith and shane-melton authored Feb 3, 2025
1 parent 3c01abc commit 101cd94
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CipherId, OrganizationId } from "@bitwarden/common/types/guid";
import { SecurityTask, SecurityTaskStatus, SecurityTaskType } from "@bitwarden/vault";

/**
* Request type for creating tasks.
* @property cipherId - Optional. The ID of the cipher to create the task for.
* @property type - The type of task to create. Currently defined as "updateAtRiskCredential".
*/
export type CreateTasksRequest = Readonly<{
cipherId?: CipherId;
type: SecurityTaskType.UpdateAtRiskCredential;
}>;

export abstract class AdminTaskService {
/**
* Retrieves all tasks for a given organization.
* @param organizationId - The ID of the organization to retrieve tasks for.
* @param status - Optional. The status of the tasks to retrieve.
*/
abstract getAllTasks(
organizationId: OrganizationId,
status?: SecurityTaskStatus | undefined,
): Promise<SecurityTask[]>;

/**
* Creates multiple tasks for a given organization and sends out notifications to applicable users.
* @param organizationId - The ID of the organization to create tasks for.
* @param tasks - The tasks to create.
*/
abstract bulkCreateTasks(
organizationId: OrganizationId,
tasks: CreateTasksRequest[],
): Promise<void>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { MockProxy, mock } from "jest-mock-extended";

import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CipherId, OrganizationId } from "@bitwarden/common/types/guid";
import { SecurityTaskStatus, SecurityTaskType } from "@bitwarden/vault";

import { CreateTasksRequest } from "./abstractions/admin-task.abstraction";
import { DefaultAdminTaskService } from "./default-admin-task.service";

describe("DefaultAdminTaskService", () => {
let defaultAdminTaskService: DefaultAdminTaskService;
let apiService: MockProxy<ApiService>;

beforeEach(() => {
apiService = mock<ApiService>();
defaultAdminTaskService = new DefaultAdminTaskService(apiService);
});

describe("getAllTasks", () => {
it("should call the api service with the correct parameters with status", async () => {
const organizationId = "orgId" as OrganizationId;
const status = SecurityTaskStatus.Pending;
const expectedUrl = `/tasks/organization?organizationId=${organizationId}&status=0`;

await defaultAdminTaskService.getAllTasks(organizationId, status);

expect(apiService.send).toHaveBeenCalledWith("GET", expectedUrl, null, true, true);
});

it("should call the api service with the correct parameters without status", async () => {
const organizationId = "orgId" as OrganizationId;
const expectedUrl = `/tasks/organization?organizationId=${organizationId}`;

await defaultAdminTaskService.getAllTasks(organizationId);

expect(apiService.send).toHaveBeenCalledWith("GET", expectedUrl, null, true, true);
});
});

describe("bulkCreateTasks", () => {
it("should call the api service with the correct parameters", async () => {
const organizationId = "orgId" as OrganizationId;
const tasks: CreateTasksRequest[] = [
{
cipherId: "cipherId-1" as CipherId,
type: SecurityTaskType.UpdateAtRiskCredential,
},
{
cipherId: "cipherId-2" as CipherId,
type: SecurityTaskType.UpdateAtRiskCredential,
},
];

await defaultAdminTaskService.bulkCreateTasks(organizationId, tasks);

expect(apiService.send).toHaveBeenCalledWith(
"POST",
`/tasks/${organizationId}/bulk-create`,
tasks,
true,
true,
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Injectable } from "@angular/core";

import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { OrganizationId } from "@bitwarden/common/types/guid";
import {
SecurityTask,
SecurityTaskData,
SecurityTaskResponse,
SecurityTaskStatus,
} from "@bitwarden/vault";

import { AdminTaskService, CreateTasksRequest } from "./abstractions/admin-task.abstraction";

@Injectable()
export class DefaultAdminTaskService implements AdminTaskService {
constructor(private apiService: ApiService) {}

async getAllTasks(
organizationId: OrganizationId,
status?: SecurityTaskStatus | undefined,
): Promise<SecurityTask[]> {
const queryParams = new URLSearchParams();

queryParams.append("organizationId", organizationId);
if (status !== undefined) {
queryParams.append("status", status.toString());
}

const r = await this.apiService.send(
"GET",
`/tasks/organization?${queryParams.toString()}`,
null,
true,
true,
);
const response = new ListResponse(r, SecurityTaskResponse);

return response.data.map((d) => new SecurityTask(new SecurityTaskData(d)));
}

async bulkCreateTasks(
organizationId: OrganizationId,
tasks: CreateTasksRequest[],
): Promise<void> {
await this.apiService.send("POST", `/tasks/${organizationId}/bulk-create`, tasks, true, true);
}
}
2 changes: 2 additions & 0 deletions libs/vault/src/tasks/models/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from "./security-task";
export * from "./security-task.data";
export * from "./security-task.response";

0 comments on commit 101cd94

Please sign in to comment.