1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 08:43:33 +00:00

Merge branch 'main' into autofill/pm-8027-inline-menu-appears-within-input-fields-that-do-not-relate-to-user-login

This commit is contained in:
Cesar Gonzalez
2024-06-03 07:57:30 -05:00
21 changed files with 240 additions and 99 deletions

View File

@@ -763,7 +763,7 @@
"message": "Kilidi aç"
},
"additionalOptions": {
"message": "Additional options"
"message": "Əlavə seçimlər"
},
"enableContextMenuItem": {
"message": "Konteks menyu seçimlərini göstər"
@@ -803,7 +803,7 @@
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
},
"exportFrom": {
"message": "Export from"
"message": "Buradan xaricə köçür"
},
"exportVault": {
"message": "Anbarı xaricə köçür"
@@ -812,28 +812,28 @@
"message": "Fayl formatı"
},
"fileEncryptedExportWarningDesc": {
"message": "This file export will be password protected and require the file password to decrypt."
"message": "Bu faylın xaricə köçürülməsi, parolla qorunacaq və şifrəsini açmaq üçün fayl parolu tələb olunacaq."
},
"filePassword": {
"message": "File password"
"message": "Fayl parolu"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
"message": "Bu parol, bu faylı daxilə və xaricə köçürmək üçün istifadə olunacaq"
},
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
"message": "Xaricə köçürməni şifrələmək və daxilə köçürməni yalnız mövcud Bitwarden hesabı ilə məhdudlaşdırmaq üçün hesabınızın istifadəçi adı və Ana Parolundan əldə edilən hesab şifrələmə açarınızı istifadə edin."
},
"passwordProtectedOptionDescription": {
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
"message": "Xaricə köçürməni şifrələmək üçün bir fayl parolu təyin edin və şifrəni açma parolunu istifadə edərək bunu istənilən Bitwarden hesabına köçürün."
},
"exportTypeHeading": {
"message": "Export type"
"message": "Xaricə köçürmə növü"
},
"accountRestricted": {
"message": "Account restricted"
"message": "Hesab məhdudlaşdırıldı"
},
"filePasswordAndConfirmFilePasswordDoNotMatch": {
"message": "“File password” and “Confirm file password“ do not match."
"message": "\"Fayl parolu\" və \"Fayl parolunu təsdiqlə\" uyuşmur."
},
"warning": {
"message": "XƏBƏRDARLIQ",
@@ -2213,10 +2213,10 @@
}
},
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
"message": "Təşkilat anbarını xaricə köçürmə"
},
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"message": "Yalnız $ORGANIZATION$ ilə əlaqələndirilmiş təşkilat anbarı ixrac ediləcək. Fərdi anbardakı və digər təşkilat elementlər daxil edilmir.",
"placeholders": {
"organization": {
"content": "$1",

View File

@@ -821,7 +821,7 @@
"message": "Dieses Passwort wird zum Exportieren und Importieren dieser Datei verwendet"
},
"accountRestrictedOptionDescription": {
"message": "Verwende den Verschlüsselungscode deines Kontos, abgeleitet vom Benutzernamen und Master-Passwort, um den Export zu verschlüsseln und den Import auf das aktuelle Bitwarden-Konto zu beschränken."
"message": "Verwende den Verschlüsselungsschlüssel deines Kontos, abgeleitet vom Benutzernamen und Master-Passwort, um den Export zu verschlüsseln und den Import auf das aktuelle Bitwarden-Konto zu beschränken."
},
"passwordProtectedOptionDescription": {
"message": "Lege ein Dateipasswort fest, um den Export zu verschlüsseln und importiere ihn in ein beliebiges Bitwarden-Konto, wobei das Passwort zum Entschlüsseln genutzt wird."

View File

@@ -423,7 +423,7 @@
"message": "Kita"
},
"unlockMethods": {
"message": "Unlock options"
"message": "Atrakinti parinktis"
},
"unlockMethodNeededToChangeTimeoutActionDesc": {
"message": "Nustatyk atrakinimo būdą, kad pakeistum saugyklos laiko limito veiksmą."
@@ -432,10 +432,10 @@
"message": "Nustatykite nustatymuose atrakinimo metodą"
},
"sessionTimeoutHeader": {
"message": "Session timeout"
"message": "Baigėsi seanso laikas"
},
"otherOptions": {
"message": "Other options"
"message": "Kitos parinktys"
},
"rateExtension": {
"message": "Įvertinkite šį plėtinį"
@@ -2274,7 +2274,7 @@
"message": "Sugeneruoti el. pašto slapyvardį su išorine persiuntimo paslauga."
},
"forwarderError": {
"message": "$SERVICENAME$ error: $ERRORMESSAGE$",
"message": "$SERVICENAME$“ klaida: $ERRORMESSAGE$.",
"description": "Reports an error returned by a forwarding service to the user.",
"placeholders": {
"servicename": {
@@ -2288,11 +2288,11 @@
}
},
"forwarderGeneratedBy": {
"message": "Generated by Bitwarden.",
"message": "Sugeneravo „Bitwarden.",
"description": "Displayed with the address on the forwarding service's configuration screen."
},
"forwarderGeneratedByWithWebsite": {
"message": "Website: $WEBSITE$. Generated by Bitwarden.",
"message": "Svetainė: $WEBSITE$. Sugeneravo „Bitwarden.",
"description": "Displayed with the address on the forwarding service's configuration screen.",
"placeholders": {
"WEBSITE": {
@@ -2302,7 +2302,7 @@
}
},
"forwaderInvalidToken": {
"message": "Invalid $SERVICENAME$ API token",
"message": "Netinkamas „$SERVICENAME$ API prieigos raktas.",
"description": "Displayed when the user's API token is empty or rejected by the forwarding service.",
"placeholders": {
"servicename": {
@@ -2312,7 +2312,7 @@
}
},
"forwaderInvalidTokenWithMessage": {
"message": "Invalid $SERVICENAME$ API token: $ERRORMESSAGE$",
"message": "Netinkamas „$SERVICENAME$ API prieigos raktas: $ERRORMESSAGE$.",
"description": "Displayed when the user's API token is rejected by the forwarding service with an error message.",
"placeholders": {
"servicename": {
@@ -2326,7 +2326,7 @@
}
},
"forwarderNoAccountId": {
"message": "Unable to obtain $SERVICENAME$ masked email account ID.",
"message": "Nepavyksta gauti „$SERVICENAME$“ užmaskuoto el. pašto paskyros ID.",
"description": "Displayed when the forwarding service fails to return an account ID.",
"placeholders": {
"servicename": {
@@ -2336,7 +2336,7 @@
}
},
"forwarderNoDomain": {
"message": "Invalid $SERVICENAME$ domain.",
"message": "Netinkamas „$SERVICENAME$ domenas.",
"description": "Displayed when the domain is empty or domain authorization failed at the forwarding service.",
"placeholders": {
"servicename": {
@@ -2346,7 +2346,7 @@
}
},
"forwarderNoUrl": {
"message": "Invalid $SERVICENAME$ url.",
"message": "Netinkamas „$SERVICENAME$“ URL.",
"description": "Displayed when the url of the forwarding service wasn't supplied.",
"placeholders": {
"servicename": {
@@ -2356,7 +2356,7 @@
}
},
"forwarderUnknownError": {
"message": "Unknown $SERVICENAME$ error occurred.",
"message": "Įvyko nežinoma „$SERVICENAME$“ klaida.",
"description": "Displayed when the forwarding service failed due to an unknown error.",
"placeholders": {
"servicename": {
@@ -2366,7 +2366,7 @@
}
},
"forwarderUnknownForwarder": {
"message": "Unknown forwarder: '$SERVICENAME$'.",
"message": "Nežinomas persiuntėjas: $SERVICENAME$.",
"description": "Displayed when the forwarding service is not supported.",
"placeholders": {
"servicename": {
@@ -3287,13 +3287,13 @@
"message": "Administratoriaus konsolės"
},
"accountSecurity": {
"message": "Account security"
"message": "Paskyros saugumas"
},
"notifications": {
"message": "Notifications"
"message": "Pranešimai"
},
"appearance": {
"message": "Appearance"
"message": "Išvaizda"
},
"errorAssigningTargetCollection": {
"message": "Klaida priskiriant tikslinę kolekciją."

View File

@@ -763,7 +763,7 @@
"message": "Lås upp"
},
"additionalOptions": {
"message": "Additional options"
"message": "Ytterligare alternativ"
},
"enableContextMenuItem": {
"message": "Visa alternativ för snabbmenyn"
@@ -803,7 +803,7 @@
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
},
"exportFrom": {
"message": "Export from"
"message": "Exportera från"
},
"exportVault": {
"message": "Exportera valv"
@@ -815,7 +815,7 @@
"message": "This file export will be password protected and require the file password to decrypt."
},
"filePassword": {
"message": "File password"
"message": "Fillösenord"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
@@ -827,7 +827,7 @@
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
},
"exportTypeHeading": {
"message": "Export type"
"message": "Exporttyp"
},
"accountRestricted": {
"message": "Account restricted"

View File

@@ -763,7 +763,7 @@
"message": "Розблокувати"
},
"additionalOptions": {
"message": "Additional options"
"message": "Додаткові налаштування"
},
"enableContextMenuItem": {
"message": "Показувати в контекстному меню"
@@ -803,7 +803,7 @@
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
},
"exportFrom": {
"message": "Export from"
"message": "Експортувати з"
},
"exportVault": {
"message": "Експортувати сховище"
@@ -812,28 +812,28 @@
"message": "Формат файлу"
},
"fileEncryptedExportWarningDesc": {
"message": "This file export will be password protected and require the file password to decrypt."
"message": "Цей експортований файл буде захищений паролем, який необхідно ввести для його розшифрування."
},
"filePassword": {
"message": "File password"
"message": "Пароль файлу"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
"message": "Цей пароль буде використано для експортування та імпортування цього файлу"
},
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
"message": "Використовуйте ключ шифрування свого облікового запису, створений на основі імені користувача й головного пароля, щоб зашифрувати експортовані дані та обмежити можливість імпортування лише до поточного облікового запису Bitwarden."
},
"passwordProtectedOptionDescription": {
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
"message": "Встановіть пароль файлу, щоб зашифрувати експортовані дані та імпортувати до будь-якого облікового запису Bitwarden за допомогою цього пароля."
},
"exportTypeHeading": {
"message": "Export type"
"message": "Тип експорту"
},
"accountRestricted": {
"message": "Account restricted"
"message": "Обмежено обліковим записом"
},
"filePasswordAndConfirmFilePasswordDoNotMatch": {
"message": "“File password” and “Confirm file password“ do not match."
"message": "Пароль файлу та підтвердження пароля відрізняються."
},
"warning": {
"message": "ПОПЕРЕДЖЕННЯ",
@@ -2213,10 +2213,10 @@
}
},
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
"message": "Експортування сховища організації"
},
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"message": "Буде експортовано лише сховище організації, пов'язане з $ORGANIZATION$. Елементи особистих сховищ або інших організацій не будуть включені.",
"placeholders": {
"organization": {
"content": "$1",

View File

@@ -821,10 +821,10 @@
"message": "此密码将用于导出和导入此文件"
},
"accountRestrictedOptionDescription": {
"message": "使用衍生自您账户的用户名和主密码的加密密钥,以加密此导出并限制只能导入到当前的 Bitwarden 账户。"
"message": "使用衍生自您账户的用户名和主密码的账户加密密钥,以加密此导出并限制只能导入到当前的 Bitwarden 账户。"
},
"passwordProtectedOptionDescription": {
"message": "设置一个密码用来加密导出的数据,并使用此密码解密以导入到任意 Bitwarden 账户。"
"message": "设置一个文件密码用来加密导出,并使用此密码解密以导入到任意 Bitwarden 账户。"
},
"exportTypeHeading": {
"message": "导出类型"

View File

@@ -1300,7 +1300,7 @@
"description": "ex. Date this password was updated"
},
"exportFrom": {
"message": "Export from"
"message": "Buradan xaricə köçür"
},
"exportVault": {
"message": "Anbarı xaricə köçür"
@@ -1309,31 +1309,31 @@
"message": "Fayl formatı"
},
"fileEncryptedExportWarningDesc": {
"message": "This file export will be password protected and require the file password to decrypt."
"message": "Bu faylın xaricə köçürülməsi, parolla qorunacaq və şifrəsini açmaq üçün fayl parolu tələb olunacaq."
},
"filePassword": {
"message": "File password"
"message": "Fayl parolu"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
"message": "Bu parol, bu faylı daxilə və xaricə köçürmək üçün istifadə olunacaq"
},
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
"message": "Xaricə köçürməni şifrələmək və daxilə köçürməni yalnız mövcud Bitwarden hesabı ilə məhdudlaşdırmaq üçün hesabınızın istifadəçi adı və Ana Parolundan əldə edilən hesab şifrələmə açarınızı istifadə edin."
},
"passwordProtected": {
"message": "Password protected"
"message": "Parolla qorunan"
},
"passwordProtectedOptionDescription": {
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
"message": "Xaricə köçürməni şifrələmək üçün bir fayl parolu təyin edin və şifrəni açma parolunu istifadə edərək bunu istənilən Bitwarden hesabına köçürün."
},
"exportTypeHeading": {
"message": "Export type"
"message": "Xaricə köçürmə növü"
},
"accountRestricted": {
"message": "Account restricted"
"message": "Hesab məhdudlaşdırıldı"
},
"filePasswordAndConfirmFilePasswordDoNotMatch": {
"message": "“File password” and “Confirm file password“ do not match."
"message": "\"Fayl parolu\" və \"Fayl parolunu təsdiqlə\" uyuşmur."
},
"hCaptchaUrl": {
"message": "hCaptcha ünvanı",
@@ -2102,10 +2102,10 @@
}
},
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
"message": "Təşkilat anbarını xaricə köçürmə"
},
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"message": "Yalnız $ORGANIZATION$ ilə əlaqələndirilmiş təşkilat anbarı ixrac ediləcək. Fərdi anbardakı və digər təşkilat elementlər daxil edilmir.",
"placeholders": {
"organization": {
"content": "$1",

View File

@@ -1318,7 +1318,7 @@
"message": "Dieses Passwort wird zum Exportieren und Importieren dieser Datei verwendet"
},
"accountRestrictedOptionDescription": {
"message": "Verwende den Verschlüsselungscode deines Kontos, abgeleitet vom Benutzernamen und Master-Passwort, um den Export zu verschlüsseln und den Import auf das aktuelle Bitwarden-Konto zu beschränken."
"message": "Verwende den Verschlüsselungsschlüssel deines Kontos, abgeleitet vom Benutzernamen und Master-Passwort, um den Export zu verschlüsseln und den Import auf das aktuelle Bitwarden-Konto zu beschränken."
},
"passwordProtected": {
"message": "Passwortgeschützt"

View File

@@ -1300,7 +1300,7 @@
"description": "ex. Date this password was updated"
},
"exportFrom": {
"message": "Export from"
"message": "Exportera från"
},
"exportVault": {
"message": "Exportera valv"

View File

@@ -1300,7 +1300,7 @@
"description": "ex. Date this password was updated"
},
"exportFrom": {
"message": "Export from"
"message": "Експортувати з"
},
"exportVault": {
"message": "Експортувати сховище"
@@ -1309,31 +1309,31 @@
"message": "Формат файлу"
},
"fileEncryptedExportWarningDesc": {
"message": "This file export will be password protected and require the file password to decrypt."
"message": "Цей експортований файл буде захищений паролем, який необхідно ввести для його розшифрування."
},
"filePassword": {
"message": "File password"
"message": "Пароль файлу"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
"message": "Цей пароль буде використано для експортування та імпортування цього файлу"
},
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
"message": "Використовуйте ключ шифрування свого облікового запису, створений на основі імені користувача й головного пароля, щоб зашифрувати експортовані дані та обмежити можливість імпортування лише до поточного облікового запису Bitwarden."
},
"passwordProtected": {
"message": "Password protected"
"message": "Захищено паролем"
},
"passwordProtectedOptionDescription": {
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
"message": "Встановіть пароль файлу, щоб зашифрувати експортовані дані та імпортувати до будь-якого облікового запису Bitwarden за допомогою цього пароля."
},
"exportTypeHeading": {
"message": "Export type"
"message": "Тип експорту"
},
"accountRestricted": {
"message": "Account restricted"
"message": "Обмежено обліковим записом"
},
"filePasswordAndConfirmFilePasswordDoNotMatch": {
"message": "“File password” and “Confirm file password“ do not match."
"message": "Пароль файлу та підтвердження пароля відрізняються."
},
"hCaptchaUrl": {
"message": "URL-адреса hCaptcha",
@@ -2102,10 +2102,10 @@
}
},
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
"message": "Експортування сховища організації"
},
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"message": "Буде експортовано лише сховище організації, пов'язане з $ORGANIZATION$. Елементи особистих сховищ або інших організацій не будуть включені.",
"placeholders": {
"organization": {
"content": "$1",

View File

@@ -1300,7 +1300,7 @@
"description": "ex. Date this password was updated"
},
"exportFrom": {
"message": "Export from"
"message": "导出自"
},
"exportVault": {
"message": "导出密码库"
@@ -1309,31 +1309,31 @@
"message": "文件格式"
},
"fileEncryptedExportWarningDesc": {
"message": "This file export will be password protected and require the file password to decrypt."
"message": "此文件导出将受密码保护,需要文件密码才能解密。"
},
"filePassword": {
"message": "File password"
"message": "文件密码"
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
"message": "此密码将用于导出和导入此文件"
},
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
"message": "使用衍生自您账户的用户名和主密码的账户加密密钥,以加密此导出并限制只能导入到当前的 Bitwarden 账户。"
},
"passwordProtected": {
"message": "Password protected"
"message": "密码保护"
},
"passwordProtectedOptionDescription": {
"message": "Set a file password to encrypt the export and import it to any Bitwarden account using the password for decryption."
"message": "设置一个文件密码用来加密此导出,并使用此密码解密以导入到任意 Bitwarden 账户。"
},
"exportTypeHeading": {
"message": "Export type"
"message": "导出类型"
},
"accountRestricted": {
"message": "Account restricted"
"message": "账户受限"
},
"filePasswordAndConfirmFilePasswordDoNotMatch": {
"message": "“File password” and “Confirm file password“ do not match."
"message": "「文件密码」与「确认文件密码」不一致。"
},
"hCaptchaUrl": {
"message": "hCaptcha URL",
@@ -2102,10 +2102,10 @@
}
},
"exportingOrganizationVaultTitle": {
"message": "Exporting organization vault"
"message": "正在导出组织密码库"
},
"exportingOrganizationVaultDesc": {
"message": "Only the organization vault associated with $ORGANIZATION$ will be exported. Items in individual vaults or other organizations will not be included.",
"message": "仅会导出与 $ORGANIZATION$ 关联的组织密码库数据。不包括个人密码库和其他组织中的项目。",
"placeholders": {
"organization": {
"content": "$1",

View File

@@ -20,8 +20,8 @@ export class WebauthnLoginAttestationResponseRequest extends WebauthnLoginAuthen
}
this.response = {
attestationObject: Utils.fromBufferToB64(credential.response.attestationObject),
clientDataJson: Utils.fromBufferToB64(credential.response.clientDataJSON),
attestationObject: Utils.fromBufferToUrlB64(credential.response.attestationObject),
clientDataJson: Utils.fromBufferToUrlB64(credential.response.clientDataJSON),
};
}
}

View File

@@ -2105,7 +2105,7 @@
"message": "Bitwarden 家庭版计划。"
},
"addons": {
"message": "附加项目"
"message": "插件"
},
"premiumAccess": {
"message": "高级会员"

View File

@@ -1,4 +1,11 @@
{
"presets": ["@babel/preset-env"],
"presets": [
[
"@babel/preset-env",
{
"bugfixes": true
}
]
],
"plugins": ["@angular/compiler-cli/linker/babel"]
}

View File

@@ -1,9 +1,52 @@
import { firstValueFrom } from "rxjs";
import { OrganizationAuthRequestService } from "@bitwarden/bit-common/admin-console/auth-requests";
import { Response } from "@bitwarden/cli/models/response";
import { MessageResponse } from "@bitwarden/cli/models/response/message.response";
import { OrganizationService } from "@bitwarden/common/admin-console/services/organization/organization.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
export class ApproveAllCommand {
constructor() {}
constructor(
private organizationAuthRequestService: OrganizationAuthRequestService,
private organizationService: OrganizationService,
) {}
async run(organizationId: string): Promise<Response> {
throw new Error("Not implemented");
if (organizationId != null) {
organizationId = organizationId.toLowerCase();
}
if (!Utils.isGuid(organizationId)) {
return Response.badRequest("`" + organizationId + "` is not a GUID.");
}
const organization = await firstValueFrom(this.organizationService.get$(organizationId));
if (!organization?.canManageUsersPassword) {
return Response.error(
"You do not have permission to approve pending device authorization requests.",
);
}
try {
const pendingApprovals =
await this.organizationAuthRequestService.listPendingRequests(organizationId);
if (pendingApprovals.length == 0) {
const res = new MessageResponse(
"No pending device authorization requests to approve.",
null,
);
return Response.success(res);
}
await this.organizationAuthRequestService.approvePendingRequests(
organizationId,
pendingApprovals,
);
return Response.success();
} catch (e) {
return Response.error(e);
}
}
}

View File

@@ -3,6 +3,8 @@ import { program, Command } from "commander";
import { BaseProgram } from "@bitwarden/cli/base-program";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ServiceContainer } from "../../service-container";
import { ApproveAllCommand } from "./approve-all.command";
import { ApproveCommand } from "./approve.command";
import { DenyAllCommand } from "./deny-all.command";
@@ -10,6 +12,10 @@ import { DenyCommand } from "./deny.command";
import { ListCommand } from "./list.command";
export class DeviceApprovalProgram extends BaseProgram {
constructor(protected serviceContainer: ServiceContainer) {
super(serviceContainer);
}
register() {
program.addCommand(this.deviceApprovalCommand());
}
@@ -32,7 +38,10 @@ export class DeviceApprovalProgram extends BaseProgram {
await this.exitIfFeatureFlagDisabled(FeatureFlag.BulkDeviceApproval);
await this.exitIfLocked();
const cmd = new ListCommand();
const cmd = new ListCommand(
this.serviceContainer.organizationAuthRequestService,
this.serviceContainer.organizationService,
);
const response = await cmd.run(organizationId);
this.processResponse(response);
});
@@ -53,14 +62,17 @@ export class DeviceApprovalProgram extends BaseProgram {
}
private approveAllCommand(): Command {
return new Command("approveAll")
return new Command("approve-all")
.description("Approve all pending requests for an organization")
.argument("<organizationId>")
.action(async (organizationId: string) => {
await this.exitIfFeatureFlagDisabled(FeatureFlag.BulkDeviceApproval);
await this.exitIfLocked();
const cmd = new ApproveAllCommand();
const cmd = new ApproveAllCommand(
this.serviceContainer.organizationAuthRequestService,
this.serviceContainer.organizationService,
);
const response = await cmd.run(organizationId);
this.processResponse(response);
});
@@ -81,7 +93,7 @@ export class DeviceApprovalProgram extends BaseProgram {
}
private denyAllCommand(): Command {
return new Command("denyAll")
return new Command("deny-all")
.description("Deny all pending requests for an organization")
.argument("<organizationId>")
.action(async (organizationId: string) => {

View File

@@ -1,9 +1,42 @@
import { firstValueFrom } from "rxjs";
import { OrganizationAuthRequestService } from "@bitwarden/bit-common/admin-console/auth-requests";
import { Response } from "@bitwarden/cli/models/response";
import { ListResponse } from "@bitwarden/cli/models/response/list.response";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { PendingAuthRequestResponse } from "./pending-auth-request.response";
export class ListCommand {
constructor() {}
constructor(
private organizationAuthRequestService: OrganizationAuthRequestService,
private organizationService: OrganizationService,
) {}
async run(organizationId: string): Promise<Response> {
throw new Error("Not implemented");
if (organizationId != null) {
organizationId = organizationId.toLowerCase();
}
if (!Utils.isGuid(organizationId)) {
return Response.badRequest("`" + organizationId + "` is not a GUID.");
}
const organization = await firstValueFrom(this.organizationService.get$(organizationId));
if (!organization?.canManageUsersPassword) {
return Response.error(
"You do not have permission to approve pending device authorization requests.",
);
}
try {
const requests =
await this.organizationAuthRequestService.listPendingRequests(organizationId);
const res = new ListResponse(requests.map((r) => new PendingAuthRequestResponse(r)));
return Response.success(res);
} catch (e) {
return Response.error(e);
}
}
}

View File

@@ -0,0 +1,26 @@
import { PendingAuthRequestView } from "@bitwarden/bit-common/admin-console/auth-requests/";
import { BaseResponse } from "@bitwarden/cli/models/response/base.response";
export class PendingAuthRequestResponse implements BaseResponse {
object = "auth-request";
id: string;
userId: string;
organizationUserId: string;
email: string;
requestDeviceIdentifier: string;
requestDeviceType: string;
requestIpAddress: string;
creationDate: Date;
constructor(authRequest: PendingAuthRequestView) {
this.id = authRequest.id;
this.userId = authRequest.userId;
this.organizationUserId = authRequest.organizationUserId;
this.email = authRequest.email;
this.requestDeviceIdentifier = authRequest.requestDeviceIdentifier;
this.requestDeviceType = authRequest.requestDeviceType;
this.requestIpAddress = authRequest.requestIpAddress;
this.creationDate = authRequest.creationDate;
}
}

View File

@@ -1,7 +1,24 @@
import {
OrganizationAuthRequestService,
OrganizationAuthRequestApiService,
} from "@bitwarden/bit-common/admin-console/auth-requests";
import { ServiceContainer as OssServiceContainer } from "@bitwarden/cli/service-container";
/**
* Instantiates services and makes them available for dependency injection.
* Any Bitwarden-licensed services should be registered here.
*/
export class ServiceContainer extends OssServiceContainer {}
export class ServiceContainer extends OssServiceContainer {
organizationAuthRequestApiService: OrganizationAuthRequestApiService;
organizationAuthRequestService: OrganizationAuthRequestService;
constructor() {
super();
this.organizationAuthRequestApiService = new OrganizationAuthRequestApiService(this.apiService);
this.organizationAuthRequestService = new OrganizationAuthRequestService(
this.organizationAuthRequestApiService,
this.cryptoService,
this.organizationUserService,
);
}
}

View File

@@ -21,7 +21,8 @@
"@bitwarden/vault-export-core": [
"../../libs/tools/export/vault-export/vault-export-core/src"
],
"@bitwarden/node/*": ["../../libs/node/src/*"]
"@bitwarden/node/*": ["../../libs/node/src/*"],
"@bitwarden/bit-common/*": ["../../bitwarden_license/bit-common/src/*"]
}
},
"include": ["src", "src/**/*.spec.ts"]

View File

@@ -1,2 +1,4 @@
export * from "./pending-organization-auth-request.response";
export * from "./organization-auth-request.service";
export * from "./organization-auth-request-api.service";
export * from "./pending-auth-request.view";