mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 08:26:11 +00:00
Ever since we started bundling the app with webpack, there’s been less and less overlap between our ‘static’ directory (files belonging to the frontend app) and Django’s interpretation of the ‘static’ directory (files served directly to the web). Split the app out to its own ‘web’ directory outside of ‘static’, and remove all the custom collectstatic --ignore rules. This makes it much clearer what’s actually being served to the web, and what’s being bundled by webpack. It also shrinks the release tarball by 3%. Signed-off-by: Anders Kaseorg <anders@zulip.com>
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import {zxcvbn, zxcvbnOptions} from "@zxcvbn-ts/core";
|
|
import zxcvbnCommonPackage from "@zxcvbn-ts/language-common";
|
|
import zxcvbnEnPackage from "@zxcvbn-ts/language-en";
|
|
|
|
import {$t} from "./i18n";
|
|
|
|
zxcvbnOptions.setOptions({
|
|
translations: zxcvbnEnPackage.translations,
|
|
dictionary: {
|
|
...zxcvbnCommonPackage.dictionary,
|
|
...zxcvbnEnPackage.dictionary,
|
|
},
|
|
});
|
|
|
|
// Note: this module is loaded asynchronously from the app with
|
|
// import() to keep zxcvbn out of the initial page load. Do not
|
|
// import it synchronously from the app.
|
|
|
|
// Return a boolean indicating whether the password is acceptable.
|
|
// Also updates a Bootstrap progress bar control (a jQuery object)
|
|
// if provided.
|
|
export function password_quality(
|
|
password: string,
|
|
$bar: JQuery | undefined,
|
|
$password_field: JQuery,
|
|
): boolean {
|
|
const min_length = $password_field.data("minLength");
|
|
const min_guesses = $password_field.data("minGuesses");
|
|
|
|
const result = zxcvbn(password);
|
|
const acceptable = password.length >= min_length && result.guesses >= min_guesses;
|
|
|
|
if ($bar !== undefined) {
|
|
const t = result.crackTimesSeconds.offlineSlowHashing1e4PerSecond;
|
|
let bar_progress = Math.min(1, Math.log(1 + t) / 22);
|
|
|
|
// Even if zxcvbn loves your short password, the bar should be
|
|
// filled at most 1/3 of the way, because we won't accept it.
|
|
if (!acceptable) {
|
|
bar_progress = Math.min(bar_progress, 0.33);
|
|
}
|
|
|
|
// The bar bottoms out at 10% so there's always something
|
|
// for the user to see.
|
|
$bar.width(`${90 * bar_progress + 10}%`)
|
|
.removeClass("bar-success bar-danger")
|
|
.addClass(acceptable ? "bar-success" : "bar-danger");
|
|
}
|
|
|
|
return acceptable;
|
|
}
|
|
|
|
export function password_warning(password: string, $password_field: JQuery): string {
|
|
const min_length = $password_field.data("minLength");
|
|
|
|
if (password.length < min_length) {
|
|
return $t(
|
|
{defaultMessage: "Password should be at least {length} characters long"},
|
|
{length: min_length},
|
|
);
|
|
}
|
|
return zxcvbn(password).feedback.warning || $t({defaultMessage: "Password is too weak"});
|
|
}
|