mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 05:13:29 +00:00
[PM-14417] Create admin TaskService (#12891)
* [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 <smelton@bitwarden.com>
This commit is contained in:
@@ -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>;
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,3 @@
|
|||||||
export * from "./security-task";
|
export * from "./security-task";
|
||||||
|
export * from "./security-task.data";
|
||||||
|
export * from "./security-task.response";
|
||||||
|
|||||||
Reference in New Issue
Block a user