mirror of
https://github.com/bitwarden/browser
synced 2026-02-16 08:34:39 +00:00
Added tests, moved method.
This commit is contained in:
@@ -16,7 +16,7 @@ import { filter, first, map, take } from "rxjs/operators";
|
||||
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { VaultFilter } from "@bitwarden/angular/vault/vault-filter/models/vault-filter.model";
|
||||
import { AuthRequestApiService } from "@bitwarden/auth/common";
|
||||
import { AuthRequestService } from "@bitwarden/auth/common";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
@@ -110,7 +110,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
private totpService: TotpService,
|
||||
private passwordRepromptService: PasswordRepromptService,
|
||||
private searchBarService: SearchBarService,
|
||||
private authRequestApiService: AuthRequestApiService,
|
||||
private authRequestService: AuthRequestService,
|
||||
private dialogService: DialogService,
|
||||
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
private toastService: ToastService,
|
||||
@@ -231,7 +231,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
this.searchBarService.setEnabled(true);
|
||||
this.searchBarService.setPlaceholderText(this.i18nService.t("searchVault"));
|
||||
|
||||
const authRequest = await this.authRequestApiService.getLastAuthRequest();
|
||||
const authRequest = await this.authRequestService.getLastAuthRequest();
|
||||
if (authRequest != null) {
|
||||
this.messagingService.send("openLoginApproval", {
|
||||
notificationId: authRequest.id,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { AuthRequestUpdateRequest } from "@bitwarden/common/auth/models/request/auth-request-update.request";
|
||||
import { AuthRequest } from "@bitwarden/common/auth/models/request/auth.request";
|
||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
|
||||
export abstract class AuthRequestApiService {
|
||||
/**
|
||||
@@ -49,9 +50,9 @@ export abstract class AuthRequestApiService {
|
||||
) => Promise<AuthRequestResponse>;
|
||||
|
||||
/**
|
||||
* Gets the most-recently-created auth request for the logged-in user.
|
||||
* Gets a list open auth requests for the logged-in user.
|
||||
*
|
||||
* @returns A promise that resolves to the auth request response.
|
||||
* @returns A promise that resolves to a list response of auth request responses.
|
||||
*/
|
||||
abstract getLastAuthRequest: () => Promise<AuthRequestResponse>;
|
||||
abstract getAuthRequests(): Promise<ListResponse<AuthRequestResponse>>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuthRequestType } from "@bitwarden/common/auth/enums/auth-request-type";
|
||||
import { AuthRequestUpdateRequest } from "@bitwarden/common/auth/models/request/auth-request-update.request";
|
||||
import { AuthRequest } from "@bitwarden/common/auth/models/request/auth.request";
|
||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
|
||||
import { DefaultAuthRequestApiService } from "./auth-request-api.service";
|
||||
|
||||
describe("DefaultAuthRequestApiService", () => {
|
||||
let service: DefaultAuthRequestApiService;
|
||||
let apiService: MockProxy<ApiService>;
|
||||
let logService: MockProxy<LogService>;
|
||||
|
||||
beforeEach(() => {
|
||||
apiService = mock<ApiService>();
|
||||
logService = mock<LogService>();
|
||||
service = new DefaultAuthRequestApiService(apiService, logService);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("getAuthRequest", () => {
|
||||
it("calls API with correct parameters", async () => {
|
||||
const requestId = "test-request-id";
|
||||
apiService.send.mockResolvedValue(true);
|
||||
|
||||
const result = await service.getAuthRequest(requestId);
|
||||
|
||||
expect(result).toBeInstanceOf(AuthRequestResponse);
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"GET",
|
||||
"/auth-requests/" + requestId,
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAuthResponse", () => {
|
||||
it("calls API with correct parameters", async () => {
|
||||
const requestId = "test-request-id";
|
||||
const accessCode = "test-access-code";
|
||||
apiService.send.mockResolvedValue(true);
|
||||
|
||||
const result = await service.getAuthResponse(requestId, accessCode);
|
||||
|
||||
expect(result).toBeInstanceOf(AuthRequestResponse);
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"GET",
|
||||
"/auth-requests/" + requestId + "/response?code=" + accessCode,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("postAdminAuthRequest", () => {
|
||||
it("calls API with correct parameters", async () => {
|
||||
const mockRequest = new AuthRequest(
|
||||
"test@test.com",
|
||||
"test-identifier",
|
||||
"test-public-key",
|
||||
AuthRequestType.AdminApproval,
|
||||
"test-access-code",
|
||||
);
|
||||
|
||||
const result = await service.postAdminAuthRequest(mockRequest);
|
||||
|
||||
expect(result).toBeInstanceOf(AuthRequestResponse);
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"POST",
|
||||
"/auth-requests/admin-request",
|
||||
mockRequest,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("postAuthRequest", () => {
|
||||
it("calls API with correct parameters", async () => {
|
||||
const mockRequest = new AuthRequest(
|
||||
"test@test.com",
|
||||
"test-identifier",
|
||||
"test-public-key",
|
||||
AuthRequestType.AuthenticateAndUnlock,
|
||||
"test-access-code",
|
||||
);
|
||||
|
||||
const result = await service.postAuthRequest(mockRequest);
|
||||
|
||||
expect(result).toBeInstanceOf(AuthRequestResponse);
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"POST",
|
||||
"/auth-requests/",
|
||||
mockRequest,
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("putAuthRequest", () => {
|
||||
it("calls API with correct parameters", async () => {
|
||||
const requestId = "test-request-id";
|
||||
const mockRequest = new AuthRequestUpdateRequest(
|
||||
"test-key",
|
||||
"test-hash",
|
||||
"test-identifier",
|
||||
true,
|
||||
);
|
||||
const result = await service.putAuthRequest(requestId, mockRequest);
|
||||
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"PUT",
|
||||
"/auth-requests/" + requestId,
|
||||
mockRequest,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
expect(result).toBeInstanceOf(AuthRequestResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAuthRequests", () => {
|
||||
it("calls API with correct parameters and return list", async () => {
|
||||
const mockResponse = { data: [{ id: "test-request-id-1" }, { id: "test-request-id-2" }] };
|
||||
apiService.send.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await service.getAuthRequests();
|
||||
|
||||
expect(apiService.send).toHaveBeenCalledWith("GET", "/auth-requests/", null, true, true);
|
||||
expect(result).toBeInstanceOf(ListResponse<AuthRequestResponse>);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -92,15 +92,4 @@ export class DefaultAuthRequestApiService implements AuthRequestApiService {
|
||||
const r = await this.apiService.send("GET", path, null, true, true);
|
||||
return new ListResponse(r, AuthRequestResponse);
|
||||
}
|
||||
|
||||
async getLastAuthRequest(): Promise<AuthRequestResponse> {
|
||||
const requests = await this.getAuthRequests();
|
||||
const activeRequests = requests.data.filter(
|
||||
(m: AuthRequestResponse) => !m.isAnswered && !m.isExpired,
|
||||
);
|
||||
const lastRequest = activeRequests.sort((a: AuthRequestResponse, b: AuthRequestResponse) =>
|
||||
a.creationDate.localeCompare(b.creationDate),
|
||||
)[activeRequests.length - 1];
|
||||
return lastRequest;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { mock } from "jest-mock-extended";
|
||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||
import { FakeMasterPasswordService } from "@bitwarden/common/key-management/master-password/services/fake-master-password.service";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -281,4 +282,21 @@ describe("AuthRequestService", () => {
|
||||
expect(phrase).toEqual(phraseUpperCase);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getLastAuthRequest", () => {
|
||||
it("should return the most recent unanswered and unexpired request", async () => {
|
||||
const mockData = {
|
||||
data: [
|
||||
{ creationDate: "2025-03-15", isAnswered: false, isExpired: false },
|
||||
{ creationDate: "2025-03-16", isAnswered: false, isExpired: false },
|
||||
],
|
||||
} as ListResponse<AuthRequestResponse>;
|
||||
|
||||
apiService.getAuthRequests.mockResolvedValue(mockData);
|
||||
|
||||
const result = await sut.getLastAuthRequest();
|
||||
|
||||
expect(result.creationDate).toBe("2025-03-16");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -203,6 +203,17 @@ export class AuthRequestService implements AuthRequestServiceAbstraction {
|
||||
};
|
||||
}
|
||||
|
||||
async getLastAuthRequest(): Promise<AuthRequestResponse> {
|
||||
const requests = await this.apiService.getAuthRequests();
|
||||
const activeRequests = requests.data.filter(
|
||||
(m: AuthRequestResponse) => !m.isAnswered && !m.isExpired,
|
||||
);
|
||||
const lastRequest = activeRequests.sort((a: AuthRequestResponse, b: AuthRequestResponse) =>
|
||||
a.creationDate.localeCompare(b.creationDate),
|
||||
)[activeRequests.length - 1];
|
||||
return lastRequest;
|
||||
}
|
||||
|
||||
sendAuthRequestPushNotification(notification: AuthRequestPushNotification): void {
|
||||
if (notification.id != null) {
|
||||
this.authRequestPushNotificationSubject.next(notification.id);
|
||||
|
||||
Reference in New Issue
Block a user