[add] helper.password
This commit is contained in:
parent
dbe388c068
commit
5fe5712587
8 changed files with 3918 additions and 2974 deletions
1705
lib/plankton/plankton.d.ts
vendored
1705
lib/plankton/plankton.d.ts
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
325
source/helpers/password.ts
Normal file
325
source/helpers/password.ts
Normal file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
Espe | Ein schlichtes Werkzeug zur Mitglieder-Verwaltung | Backend
|
||||
Copyright (C) 2024 Christian Fraß
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with this program. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace _espe.helper.password
|
||||
{
|
||||
|
||||
/**
|
||||
*/
|
||||
type char = string;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
type type_settings = {
|
||||
minimum_length : (null | int);
|
||||
maximum_length : (null | int);
|
||||
must_contain_letter : boolean;
|
||||
must_contain_number : boolean;
|
||||
must_contain_special_character : boolean;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
enum enum_character_class {
|
||||
number_ = "number",
|
||||
letter = "letter",
|
||||
special = "special",
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
const character_classification : Record<enum_character_class, Array<int>> = {
|
||||
[enum_character_class.number_]: [
|
||||
0x30,
|
||||
0x31,
|
||||
0x32,
|
||||
0x33,
|
||||
0x34,
|
||||
0x35,
|
||||
0x36,
|
||||
0x37,
|
||||
0x38,
|
||||
0x39,
|
||||
],
|
||||
[enum_character_class.letter]: [
|
||||
0x41,
|
||||
0x42,
|
||||
0x43,
|
||||
0x44,
|
||||
0x45,
|
||||
0x46,
|
||||
0x47,
|
||||
0x48,
|
||||
0x49,
|
||||
0x4A,
|
||||
0x4B,
|
||||
0x4C,
|
||||
0x4D,
|
||||
0x4E,
|
||||
0x4F,
|
||||
0x50,
|
||||
0x51,
|
||||
0x52,
|
||||
0x53,
|
||||
0x54,
|
||||
0x55,
|
||||
0x56,
|
||||
0x56,
|
||||
0x58,
|
||||
0x59,
|
||||
0x5A,
|
||||
0x61,
|
||||
0x62,
|
||||
0x63,
|
||||
0x64,
|
||||
0x65,
|
||||
0x66,
|
||||
0x67,
|
||||
0x68,
|
||||
0x69,
|
||||
0x6A,
|
||||
0x6B,
|
||||
0x6C,
|
||||
0x6D,
|
||||
0x6E,
|
||||
0x6F,
|
||||
0x70,
|
||||
0x71,
|
||||
0x72,
|
||||
0x73,
|
||||
0x74,
|
||||
0x75,
|
||||
0x76,
|
||||
0x77,
|
||||
0x78,
|
||||
0x79,
|
||||
0x7A,
|
||||
],
|
||||
[enum_character_class.special]: [
|
||||
0x20,
|
||||
0x21,
|
||||
0x22,
|
||||
0x23,
|
||||
0x24,
|
||||
0x25,
|
||||
0x26,
|
||||
0x27,
|
||||
0x28,
|
||||
0x29,
|
||||
0x2A,
|
||||
0x2B,
|
||||
0x2C,
|
||||
0x2D,
|
||||
0x2E,
|
||||
0x2F,
|
||||
0x3A,
|
||||
0x3B,
|
||||
0x3C,
|
||||
0x3D,
|
||||
0x3E,
|
||||
0x3F,
|
||||
0x40,
|
||||
0x5B,
|
||||
0x5C,
|
||||
0x5D,
|
||||
0x5E,
|
||||
0x5F,
|
||||
0x60,
|
||||
0x7B,
|
||||
0x7C,
|
||||
0x7D,
|
||||
0x7E,
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function character_is_number(
|
||||
character : char
|
||||
) : boolean
|
||||
{
|
||||
if (character.length !== 1) {
|
||||
throw (new Error("not a character"));
|
||||
}
|
||||
else {
|
||||
const code : int = character.charCodeAt(0);
|
||||
return character_classification[enum_character_class.number_].includes(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function character_is_letter(
|
||||
character : char
|
||||
) : boolean
|
||||
{
|
||||
if (character.length !== 1) {
|
||||
throw (new Error("not a character"));
|
||||
}
|
||||
else {
|
||||
const code : int = character.charCodeAt(0);
|
||||
return character_classification[enum_character_class.letter].includes(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function character_is_special(
|
||||
character : char
|
||||
) : boolean
|
||||
{
|
||||
if (character.length !== 1) {
|
||||
throw (new Error("not a character"));
|
||||
}
|
||||
else {
|
||||
const code : int = character.charCodeAt(0);
|
||||
return character_classification[enum_character_class.special].includes(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function validate(
|
||||
settings : type_settings,
|
||||
password : string
|
||||
) : Array<{incident : string; details : Record<string, any>}>
|
||||
{
|
||||
let flaws : Array<{incident : string; details : Record<string, any>}> = [];
|
||||
const characters : Array<char> = password.split("");
|
||||
if (
|
||||
(settings.minimum_length !== null)
|
||||
&&
|
||||
(password.length < settings.minimum_length)
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "too_short",
|
||||
"details": {
|
||||
"minimum_length": settings.minimum_length,
|
||||
"actual_length": password.length,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
(settings.maximum_length !== null)
|
||||
&&
|
||||
(password.length > settings.maximum_length)
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "too_long",
|
||||
"details": {
|
||||
"maximum_length": settings.maximum_length,
|
||||
"actual_length": password.length,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_letter
|
||||
&&
|
||||
(! characters.some(character => character_is_letter(character)))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_letter",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_number
|
||||
&&
|
||||
(! characters.some(character => character_is_number(character)))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_number",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_special_character
|
||||
&&
|
||||
(! characters.some(character => character_is_special(character)))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_special_character",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return flaws;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
export function generate(
|
||||
settings : type_settings
|
||||
) : string
|
||||
{
|
||||
const count_number : int = (settings.must_contain_number ? 1 : 0);
|
||||
const count_special : int = (settings.must_contain_special_character ? 1 : 0);
|
||||
const count_letter_raw : int = ((settings.minimum_length ?? 8) - count_number - count_special);
|
||||
const count_letter : int = ((settings.must_contain_letter && (count_letter_raw <= 0)) ? 1 : count_letter_raw);
|
||||
if (
|
||||
(settings.maximum_length !== null)
|
||||
&&
|
||||
((count_letter + count_number + count_special) > settings.maximum_length)
|
||||
) {
|
||||
throw (new Error("impossible"));
|
||||
}
|
||||
else {
|
||||
return lib_plankton.call.convey(
|
||||
(
|
||||
([] as Array<int>)
|
||||
.concat(
|
||||
lib_plankton.list.sequence(count_letter)
|
||||
.map(x => lib_plankton.random.choose_uniformly<int>(character_classification[enum_character_class.letter]))
|
||||
)
|
||||
.concat(
|
||||
lib_plankton.list.sequence(count_number)
|
||||
.map(x => lib_plankton.random.choose_uniformly<int>(character_classification[enum_character_class.number_]))
|
||||
)
|
||||
.concat(
|
||||
lib_plankton.list.sequence(count_special)
|
||||
.map(x => lib_plankton.random.choose_uniformly<int>(character_classification[enum_character_class.special]))
|
||||
)
|
||||
),
|
||||
[
|
||||
lib_plankton.random.shuffle<int>,
|
||||
(x : Array<int>) => x.map(y => String.fromCharCode(y)),
|
||||
(x : Array<string>) => x.join(""),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -45,90 +45,26 @@ namespace _espe.service.member
|
|||
|
||||
|
||||
/**
|
||||
* @todo do not export
|
||||
*/
|
||||
export function validate_password(
|
||||
function validate_password(
|
||||
password : string
|
||||
) : Array<{incident : string; details : Record<string, any>}>
|
||||
{
|
||||
let flaws : Array<{incident : string; details : Record<string, any>}> = [];
|
||||
const settings : {
|
||||
minimum_length : (null | int);
|
||||
maximum_length : (null | int);
|
||||
must_contain_letter : boolean;
|
||||
must_contain_number : boolean;
|
||||
must_contain_special_character : boolean;
|
||||
} = _espe.conf.get().settings.password_policy;
|
||||
if (
|
||||
(settings.minimum_length !== null)
|
||||
&&
|
||||
(password.length < settings.minimum_length)
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "too_short",
|
||||
"details": {
|
||||
"minimum_length": settings.minimum_length,
|
||||
"actual_length": password.length,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
(settings.maximum_length !== null)
|
||||
&&
|
||||
(password.length > settings.maximum_length)
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "too_long",
|
||||
"details": {
|
||||
"maximum_length": settings.maximum_length,
|
||||
"actual_length": password.length,
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_letter
|
||||
&&
|
||||
(! (new RegExp("[a-zA-Z]")).test(password))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_letter",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_number
|
||||
&&
|
||||
(! (new RegExp("[0-9]")).test(password))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_number",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (
|
||||
settings.must_contain_special_character
|
||||
&&
|
||||
(! (new RegExp("[!?-_.,;/\~%&$'()\\[\\]{}^'#|+*<>=\"`:@]")).test(password))
|
||||
) {
|
||||
flaws.push(
|
||||
{
|
||||
"incident": "lacks_special_character",
|
||||
"details": {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return flaws;
|
||||
return _espe.helper.password.validate(
|
||||
_espe.conf.get().settings.password_policy,
|
||||
password
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
function generate_password(
|
||||
) : string
|
||||
{
|
||||
return _espe.helper.password.generate(
|
||||
_espe.conf.get().settings.password_policy
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
{
|
||||
"service.member.validate_password": {
|
||||
"helper.password.validate": {
|
||||
"cases": [
|
||||
{
|
||||
"name": "minimum_length:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": 5,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": 5,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "abcde"
|
||||
},
|
||||
|
@ -23,16 +19,12 @@
|
|||
{
|
||||
"name": "minimum_length:fail",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": 5,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": 5,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "abcd"
|
||||
},
|
||||
|
@ -49,16 +41,12 @@
|
|||
{
|
||||
"name": "maximum_length:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": 5,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": 5,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "abcde"
|
||||
},
|
||||
|
@ -68,16 +56,12 @@
|
|||
{
|
||||
"name": "maximum_length:fail",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": 5,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": 5,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "abcdef"
|
||||
},
|
||||
|
@ -94,16 +78,12 @@
|
|||
{
|
||||
"name": "must_contain_letter:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "01x34"
|
||||
},
|
||||
|
@ -113,16 +93,12 @@
|
|||
{
|
||||
"name": "must_contain_letter:fail",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "01234"
|
||||
},
|
||||
|
@ -137,16 +113,12 @@
|
|||
{
|
||||
"name": "must_contain_number:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "ab0de"
|
||||
},
|
||||
|
@ -156,16 +128,12 @@
|
|||
{
|
||||
"name": "must_contain_number:fail",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": false
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": false
|
||||
},
|
||||
"password": "abcde"
|
||||
},
|
||||
|
@ -180,16 +148,12 @@
|
|||
{
|
||||
"name": "must_contain_special_character:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": true
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": true
|
||||
},
|
||||
"password": "01.34"
|
||||
},
|
||||
|
@ -199,16 +163,12 @@
|
|||
{
|
||||
"name": "must_contain_special_character:fail",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": true
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": null,
|
||||
"maximum_length": null,
|
||||
"must_contain_letter": false,
|
||||
"must_contain_number": false,
|
||||
"must_contain_special_character": true
|
||||
},
|
||||
"password": "01234"
|
||||
},
|
||||
|
@ -223,16 +183,12 @@
|
|||
{
|
||||
"name": "oblique:pass",
|
||||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"password_policy": {
|
||||
"minimum_length": 8,
|
||||
"maximum_length": 12,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": true
|
||||
}
|
||||
}
|
||||
"settings": {
|
||||
"minimum_length": 8,
|
||||
"maximum_length": 12,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": true
|
||||
},
|
||||
"password": "eiB@oo7tuu"
|
||||
},
|
||||
|
@ -276,8 +232,12 @@
|
|||
"input": {
|
||||
"conf": {
|
||||
"settings": {
|
||||
"target_domain": "testdomain.org",
|
||||
"prefix_for_numberbased_email_addresses": "wicht-"
|
||||
"organisation": {
|
||||
"domain": "testdomain.org"
|
||||
},
|
||||
"misc": {
|
||||
"prefix_for_veiled_email_addresses": "wicht-"
|
||||
}
|
||||
}
|
||||
},
|
||||
"members": [
|
||||
|
|
|
@ -24,14 +24,14 @@ const _data : Record<string, type_test_section> = lib_plankton.json.decode(nm_fs
|
|||
|
||||
|
||||
describe(
|
||||
"service.member.validate_password",
|
||||
"helper.password.validate",
|
||||
() => {
|
||||
const data : {
|
||||
cases : Array<
|
||||
{
|
||||
name : string;
|
||||
input : {
|
||||
conf : any;
|
||||
settings : any;
|
||||
password : string;
|
||||
};
|
||||
output : Array<
|
||||
|
@ -42,27 +42,56 @@ describe(
|
|||
>;
|
||||
}
|
||||
>;
|
||||
} = _data["service.member.validate_password"];
|
||||
} = _data["helper.password.validate"];
|
||||
data.cases.forEach(
|
||||
case_ => {
|
||||
it(
|
||||
case_.name,
|
||||
() => {
|
||||
_espe.conf.inject(case_.input.conf);
|
||||
// _espe.conf.inject(case_.input.conf);
|
||||
const result : Array<
|
||||
{
|
||||
incident : string;
|
||||
details : Record<string, any>;
|
||||
}
|
||||
> = _espe.service.member.validate_password(case_.input.password);
|
||||
> = _espe.helper.password.validate(case_.input.settings, case_.input.password);
|
||||
nm_assert.deepEqual(result, case_.output);
|
||||
_espe.conf.inject({});
|
||||
// _espe.conf.inject({});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
/*
|
||||
describe(
|
||||
"helper.password.generate",
|
||||
() => {
|
||||
it(
|
||||
"test",
|
||||
() => {
|
||||
lib_plankton.list.sequence(20).forEach(
|
||||
() => {
|
||||
process.stderr.write(
|
||||
_espe.helper.password.generate(
|
||||
{
|
||||
"minimum_length": 8,
|
||||
"maximum_length": 240,
|
||||
"must_contain_letter": true,
|
||||
"must_contain_number": true,
|
||||
"must_contain_special_character": true,
|
||||
}
|
||||
)
|
||||
+
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
*/
|
||||
describe(
|
||||
"service.member.name_login",
|
||||
() => {
|
||||
|
@ -95,6 +124,8 @@ describe(
|
|||
"email_redirect_to_private_address": false,
|
||||
"email_allow_sending": false,
|
||||
"password_image": null,
|
||||
"password_change_last_attempt": null,
|
||||
"password_change_token": null,
|
||||
};
|
||||
const result : string = _espe.service.member.name_login(member_object);
|
||||
nm_assert.equal(result, case_.output);
|
||||
|
@ -158,6 +189,8 @@ describe(
|
|||
"email_redirect_to_private_address": member_raw.email_redirect_to_private_address,
|
||||
"email_allow_sending": member_raw.email_allow_sending,
|
||||
"password_image": member_raw.password_image,
|
||||
"password_change_last_attempt": null,
|
||||
"password_change_token": null,
|
||||
}
|
||||
)
|
||||
),
|
||||
|
|
|
@ -45,6 +45,7 @@ node_modules:
|
|||
${dir_temp}/espe-core.js ${dir_temp}/espe-core.d.ts: \
|
||||
${dir_lib}/plankton/plankton.d.ts \
|
||||
${dir_source}/helpers.ts \
|
||||
${dir_source}/helpers/password.ts \
|
||||
${dir_source}/database.ts \
|
||||
${dir_source}/types.ts \
|
||||
${dir_source}/repositories/name_index.ts \
|
||||
|
@ -81,7 +82,7 @@ ${dir_temp}/espe-main-raw.js: \
|
|||
${dir_source}/main.ts
|
||||
@ ${cmd_log} "compile | main …"
|
||||
@ ${cmd_mkdir} $(dir $@)
|
||||
@ tsc --lib es2020 $^ --outFile $@
|
||||
@ ${cmd_tsc} --lib es2020 $^ --outFile $@
|
||||
|
||||
${dir_build}/espe: \
|
||||
${dir_source}/head.js \
|
||||
|
@ -109,7 +110,7 @@ ${dir_temp}/espe-test-raw.js: \
|
|||
${dir_source}/test/main.mocha.ts
|
||||
@ ${cmd_log} "compile | test …"
|
||||
@ ${cmd_mkdir} $(dir $@)
|
||||
@ tsc --lib es2020 $^ --outFile $@
|
||||
@ ${cmd_tsc} --lib es2020 $^ --outFile $@
|
||||
|
||||
${dir_build}/espe-test.mocha.js: \
|
||||
${dir_source}/head.js \
|
||||
|
|
|
@ -7,7 +7,9 @@ dir=lib/plankton
|
|||
modules=""
|
||||
modules="${modules} base"
|
||||
modules="${modules} call"
|
||||
modules="${modules} list"
|
||||
modules="${modules} file"
|
||||
modules="${modules} random"
|
||||
modules="${modules} sha256"
|
||||
modules="${modules} database"
|
||||
modules="${modules} storage"
|
||||
|
|
Loading…
Add table
Reference in a new issue