mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2025-03-30 15:08:29 +00:00
frontend linting
This commit is contained in:
parent
f7afc72d81
commit
53720ff740
21
.eslintrc.js
Normal file
21
.eslintrc.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es2021: true,
|
||||||
|
},
|
||||||
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 12,
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
plugins: ["@typescript-eslint"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/ban-types": "off",
|
||||||
|
indent: ["error", 2],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
quotes: ["error", "double"],
|
||||||
|
semi: ["error", "always"],
|
||||||
|
},
|
||||||
|
};
|
3
.github/workflows/linux.yml
vendored
3
.github/workflows/linux.yml
vendored
@ -80,6 +80,9 @@ jobs:
|
|||||||
|
|
||||||
# - name: build frontend
|
# - name: build frontend
|
||||||
# run: make frontend
|
# run: make frontend
|
||||||
|
#
|
||||||
|
- name: lint frontend
|
||||||
|
run: yarn lint
|
||||||
|
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: make test
|
run: make test
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
|
"lint": "yarn run eslint templates",
|
||||||
"start": "webpack-dev-server --mode development --progress --color",
|
"start": "webpack-dev-server --mode development --progress --color",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
@ -12,10 +13,13 @@
|
|||||||
"@types/jsdom": "^16.2.10",
|
"@types/jsdom": "^16.2.10",
|
||||||
"@types/node": "^15.0.2",
|
"@types/node": "^15.0.2",
|
||||||
"@types/sinon": "^10.0.0",
|
"@types/sinon": "^10.0.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.31.2",
|
||||||
|
"@typescript-eslint/parser": "^4.31.2",
|
||||||
"@wasm-tool/wasm-pack-plugin": "^1.4.0",
|
"@wasm-tool/wasm-pack-plugin": "^1.4.0",
|
||||||
"css-loader": "^5.2.4",
|
"css-loader": "^5.2.4",
|
||||||
"css-minimizer-webpack-plugin": "^2.0.0",
|
"css-minimizer-webpack-plugin": "^2.0.0",
|
||||||
"dart-sass": "^1.25.0",
|
"dart-sass": "^1.25.0",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "^3.0.3",
|
||||||
"jsdom": "^16.5.3",
|
"jsdom": "^16.5.3",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use libmcaptcha::{defense::Level, DefenseBuilder, master::messages::RemoveCaptcha};
|
use libmcaptcha::{defense::Level, master::messages::RemoveCaptcha, DefenseBuilder};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -190,8 +190,16 @@ async fn update_levels(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try_join_all(futs).await?;
|
try_join_all(futs).await?;
|
||||||
if let Err(ServiceError::CaptchaError(e)) = data.captcha.remove(RemoveCaptcha(payload.key.clone())).await {
|
if let Err(ServiceError::CaptchaError(e)) = data
|
||||||
log::error!("Deleting captcha key {} while updating it, error: {:?}", &payload.key, e)
|
.captcha
|
||||||
|
.remove(RemoveCaptcha(payload.key.clone()))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::error!(
|
||||||
|
"Deleting captcha key {} while updating it, error: {:?}",
|
||||||
|
&payload.key,
|
||||||
|
e
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Ok(HttpResponse::Ok())
|
Ok(HttpResponse::Ok())
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const ROUTES = {
|
const ROUTES = {
|
||||||
registerUser: '/api/v1/signup',
|
registerUser: "/api/v1/signup",
|
||||||
loginUser: '/api/v1/signin',
|
loginUser: "/api/v1/signin",
|
||||||
signoutUser: '/api/v1/signout',
|
signoutUser: "/api/v1/signout",
|
||||||
deleteAccount: '/api/v1/account/delete',
|
deleteAccount: "/api/v1/account/delete",
|
||||||
usernameExists: '/api/v1/account/username/exists',
|
usernameExists: "/api/v1/account/username/exists",
|
||||||
emailExists: '/api/v1/account/email/exists',
|
emailExists: "/api/v1/account/email/exists",
|
||||||
healthCheck: '/api/v1/meta/health',
|
healthCheck: "/api/v1/meta/health",
|
||||||
buildDetails: '/api/v1/meta/build',
|
buildDetails: "/api/v1/meta/build",
|
||||||
markNotificationRead: '/api/v1/notifications/read',
|
markNotificationRead: "/api/v1/notifications/read",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ROUTES;
|
export default ROUTES;
|
||||||
|
@ -14,6 +14,6 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import * as lib from 'mcaptcha-glue';
|
import * as lib from "mcaptcha-glue";
|
||||||
|
|
||||||
export const register = () => lib.init();
|
export const register = (): void => lib.init();
|
||||||
|
@ -14,38 +14,38 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {init} from 'mcaptcha-glue';
|
import {init} from "mcaptcha-glue";
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
import isBlankString from '../../../utils/isBlankString';
|
import isBlankString from "../../../utils/isBlankString";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import registerShowPassword from '../../../components/showPassword';
|
import registerShowPassword from "../../../components/showPassword";
|
||||||
import createError from '../../../components/error/index';
|
import createError from "../../../components/error/index";
|
||||||
|
|
||||||
//import '../forms.scss';
|
//import '../forms.scss';
|
||||||
|
|
||||||
export const getPassword = () => {
|
export const getPassword = (): string | null => {
|
||||||
const passwordElement = <HTMLInputElement>document.getElementById('password');
|
const passwordElement = <HTMLInputElement>document.getElementById("password");
|
||||||
if (passwordElement === null) {
|
if (passwordElement === null) {
|
||||||
console.debug('Password is null');
|
console.debug("Password is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return passwordElement.value;
|
return passwordElement.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const login = async (e: Event) => {
|
const login = async (e: Event): Promise<void> => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const loginElement = <HTMLInputElement>document.getElementById('login');
|
const loginElement = <HTMLInputElement>document.getElementById("login");
|
||||||
if (loginElement === null) {
|
if (loginElement === null) {
|
||||||
console.debug('login element element is null');
|
console.debug("login element element is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const login = loginElement.value;
|
const login = loginElement.value;
|
||||||
isBlankString(login, 'username', e);
|
isBlankString(login, "username", e);
|
||||||
|
|
||||||
const password = getPassword();
|
const password = getPassword();
|
||||||
|
|
||||||
@ -65,9 +65,9 @@ const login = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
const form = <HTMLFontElement>document.getElementById('form');
|
const form = <HTMLFontElement>document.getElementById("form");
|
||||||
form.addEventListener('submit', login, true);
|
form.addEventListener("submit", login, true);
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
init();
|
init();
|
||||||
};
|
};
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fetchMock from 'jest-fetch-mock';
|
import fetchMock from "jest-fetch-mock";
|
||||||
|
|
||||||
import emailExists from './emailExists';
|
import emailExists from "./emailExists";
|
||||||
|
|
||||||
import {mockAlert, getRegistrationFormHtml} from '../../../setUpTests';
|
import {mockAlert, getRegistrationFormHtml} from "../../../setUpTests";
|
||||||
|
|
||||||
import setup from '../../../components/error/setUpTests';
|
import setup from "../../../components/error/setUpTests";
|
||||||
|
|
||||||
fetchMock.enableMocks();
|
fetchMock.enableMocks();
|
||||||
mockAlert();
|
mockAlert();
|
||||||
@ -30,14 +30,14 @@ beforeEach(() => {
|
|||||||
fetchMock.resetMocks();
|
fetchMock.resetMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('finds exchange', async () => {
|
it("finds exchange", async () => {
|
||||||
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
||||||
|
|
||||||
document.body.innerHTML = getRegistrationFormHtml();
|
document.body.innerHTML = getRegistrationFormHtml();
|
||||||
document.querySelector('body').appendChild(setup());
|
document.querySelector("body").appendChild(setup());
|
||||||
|
|
||||||
const emailField = <HTMLInputElement>document.getElementById('email');
|
const emailField = <HTMLInputElement>document.getElementById("email");
|
||||||
emailField.setAttribute('value', 'test@a.com');
|
emailField.setAttribute("value", "test@a.com");
|
||||||
|
|
||||||
expect(await emailExists()).toBe(true);
|
expect(await emailExists()).toBe(true);
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ROUTES from '../../../api/v1/routes';
|
import ROUTES from "../../../api/v1/routes";
|
||||||
|
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error/index';
|
import createError from "../../../components/error/index";
|
||||||
|
|
||||||
const emailExists = async (element?: HTMLInputElement) => {
|
const emailExists = async (element?: HTMLInputElement): Promise<boolean> => {
|
||||||
let email;
|
let email;
|
||||||
if (element === undefined || element === null) {
|
if (element === undefined || element === null) {
|
||||||
email = <HTMLInputElement>document.getElementById('email');
|
email = <HTMLInputElement>document.getElementById("email");
|
||||||
} else {
|
} else {
|
||||||
email = element;
|
email = element;
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ const emailExists = async (element?: HTMLInputElement) => {
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (data.exists) {
|
if (data.exists) {
|
||||||
email.className += ' form__in-field--warn';
|
email.className += " form__in-field--warn";
|
||||||
createError(`Email "${val}" is already used`);
|
createError(`Email "${val}" is already used`);
|
||||||
return data.exists;
|
return data.exists;
|
||||||
}
|
}
|
||||||
|
@ -15,33 +15,33 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
import isBlankString from '../../../utils/isBlankString';
|
import isBlankString from "../../../utils/isBlankString";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
|
|
||||||
import userExists from './userExists';
|
import userExists from "./userExists";
|
||||||
import emailExists from './emailExists';
|
import emailExists from "./emailExists";
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import registerShowPassword from '../../../components/showPassword';
|
import registerShowPassword from "../../../components/showPassword";
|
||||||
import createError from '../../../components/error/index';
|
import createError from "../../../components/error/index";
|
||||||
|
|
||||||
//import '../forms.scss';
|
//import '../forms.scss';
|
||||||
|
|
||||||
const usernameElement = <HTMLInputElement>document.getElementById('username');
|
const usernameElement = <HTMLInputElement>document.getElementById("username");
|
||||||
const emailElement = <HTMLInputElement>document.getElementById('email');
|
const emailElement = <HTMLInputElement>document.getElementById("email");
|
||||||
const passwordElement = <HTMLInputElement>document.getElementById('password');
|
const passwordElement = <HTMLInputElement>document.getElementById("password");
|
||||||
|
|
||||||
const registerUser = async (e: Event) => {
|
const registerUser = async (e: Event): Promise<void> => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const username = usernameElement.value;
|
const username = usernameElement.value;
|
||||||
isBlankString(username, 'username', e);
|
isBlankString(username, "username", e);
|
||||||
//isBlankString(e);//, username, 'username');
|
//isBlankString(e);//, username, 'username');
|
||||||
|
|
||||||
const password = passwordElement.value;
|
const password = passwordElement.value;
|
||||||
const passwordCheckElement = <HTMLInputElement>(
|
const passwordCheckElement = <HTMLInputElement>(
|
||||||
document.getElementById('password-check')
|
document.getElementById("password-check")
|
||||||
);
|
);
|
||||||
const passwordCheck = passwordCheckElement.value;
|
const passwordCheck = passwordCheckElement.value;
|
||||||
if (password != passwordCheck) {
|
if (password != passwordCheck) {
|
||||||
@ -54,7 +54,7 @@ const registerUser = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let email: string | null = emailElement.value;
|
let email: string | null = emailElement.value;
|
||||||
if (!email.replace(/\s/g, '').length) {
|
if (!email.replace(/\s/g, "").length) {
|
||||||
email = null;
|
email = null;
|
||||||
} else {
|
} else {
|
||||||
exists = await emailExists();
|
exists = await emailExists();
|
||||||
@ -80,11 +80,11 @@ const registerUser = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
const form = <HTMLFontElement>document.getElementById('form');
|
const form = <HTMLFontElement>document.getElementById("form");
|
||||||
form.addEventListener('submit', registerUser, true);
|
form.addEventListener("submit", registerUser, true);
|
||||||
usernameElement.addEventListener(
|
usernameElement.addEventListener(
|
||||||
'input',
|
"input",
|
||||||
async () => await userExists(),
|
async () => await userExists(),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import fetchMock from 'jest-fetch-mock';
|
import fetchMock from "jest-fetch-mock";
|
||||||
|
|
||||||
import userExists from './userExists';
|
import userExists from "./userExists";
|
||||||
|
|
||||||
import {mockAlert, getLoginFormHtml} from '../../../setUpTests';
|
import {mockAlert, getLoginFormHtml} from "../../../setUpTests";
|
||||||
|
|
||||||
import setup from '../../../components/error/setUpTests';
|
import setup from "../../../components/error/setUpTests";
|
||||||
|
|
||||||
fetchMock.enableMocks();
|
fetchMock.enableMocks();
|
||||||
mockAlert();
|
mockAlert();
|
||||||
@ -29,16 +29,16 @@ beforeEach(() => {
|
|||||||
fetchMock.resetMocks();
|
fetchMock.resetMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('finds exchange', async () => {
|
it("finds exchange", async () => {
|
||||||
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
||||||
|
|
||||||
document.body.innerHTML = getLoginFormHtml();
|
document.body.innerHTML = getLoginFormHtml();
|
||||||
document.querySelector('body').appendChild(setup());
|
document.querySelector("body").appendChild(setup());
|
||||||
const usernameField = <HTMLInputElement>document.querySelector('#username');
|
const usernameField = <HTMLInputElement>document.querySelector("#username");
|
||||||
usernameField.value = 'test';
|
usernameField.value = "test";
|
||||||
expect(await userExists()).toBe(true);
|
expect(await userExists()).toBe(true);
|
||||||
|
|
||||||
usernameField.value = 'test';
|
usernameField.value = "test";
|
||||||
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
fetchMock.mockResponseOnce(JSON.stringify({exists: true}));
|
||||||
expect(await userExists(usernameField)).toBe(true);
|
expect(await userExists(usernameField)).toBe(true);
|
||||||
|
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ROUTES from '../../../api/v1/routes';
|
import ROUTES from "../../../api/v1/routes";
|
||||||
|
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error/index';
|
import createError from "../../../components/error/index";
|
||||||
|
|
||||||
const userExists = async (element?: HTMLInputElement) => {
|
const userExists = async (element?: HTMLInputElement): Promise<boolean> => {
|
||||||
console.log(element);
|
console.log(element);
|
||||||
let username;
|
let username;
|
||||||
if (element === undefined) {
|
if (element === undefined) {
|
||||||
username = <HTMLInputElement>document.getElementById('username');
|
username = <HTMLInputElement>document.getElementById("username");
|
||||||
} else {
|
} else {
|
||||||
username = element;
|
username = element;
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ const userExists = async (element?: HTMLInputElement) => {
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (data.exists) {
|
if (data.exists) {
|
||||||
username.className += ' form__in-field--warn';
|
username.className += " form__in-field--warn";
|
||||||
createError(`Username "${val}" taken`);
|
createError(`Username "${val}" taken`);
|
||||||
}
|
}
|
||||||
return data.exists;
|
return data.exists;
|
||||||
|
@ -15,17 +15,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import form from './index';
|
import form from "./index";
|
||||||
|
|
||||||
it('sudo form works', () => {
|
it("sudo form works", () => {
|
||||||
try {
|
try {
|
||||||
form.get();
|
form.get();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe('Element form is undefined');
|
expect(e.message).toBe("Element form is undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = document.createElement('form');
|
const element = document.createElement("form");
|
||||||
element.id = 'form';
|
element.id = "form";
|
||||||
document.body.appendChild(element);
|
document.body.appendChild(element);
|
||||||
expect(form.get()).toBe(element);
|
expect(form.get()).toBe(element);
|
||||||
});
|
});
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import LazyElement from '../../utils/lazyElement';
|
import LazyElement from "../../utils/lazyElement";
|
||||||
|
|
||||||
const ID = 'form';
|
const ID = "form";
|
||||||
const FORM = new LazyElement(ID);
|
const FORM = new LazyElement(ID);
|
||||||
|
|
||||||
export default FORM;
|
export default FORM;
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import additionalData from './index';
|
import additionalData from "./index";
|
||||||
|
|
||||||
it('sudo form works', () => {
|
it("sudo form works", () => {
|
||||||
try {
|
try {
|
||||||
additionalData();
|
additionalData();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -26,8 +26,8 @@ it('sudo form works', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = document.createElement('div');
|
const element = document.createElement("div");
|
||||||
element.id = 'additional-data';
|
element.id = "additional-data";
|
||||||
document.body.appendChild(element);
|
document.body.appendChild(element);
|
||||||
expect(additionalData()).toBe(element);
|
expect(additionalData()).toBe(element);
|
||||||
});
|
});
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const additionalData = () => {
|
const additionalData = (): HTMLElement => {
|
||||||
let element = null;
|
let element = null;
|
||||||
const ID = 'additional-data';
|
const ID = "additional-data";
|
||||||
|
|
||||||
if (element === null) {
|
if (element === null) {
|
||||||
element = <HTMLElement>document.getElementById(ID);
|
element = <HTMLElement>document.getElementById(ID);
|
||||||
@ -29,7 +29,7 @@ const additionalData = () => {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
element;
|
return element;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class CopyIcon {
|
|||||||
constructor(
|
constructor(
|
||||||
writeText: string,
|
writeText: string,
|
||||||
copyIcon: HTMLElement,
|
copyIcon: HTMLElement,
|
||||||
copyDoneIconClass: string,
|
copyDoneIconClass: string
|
||||||
) {
|
) {
|
||||||
this.copyIcon = copyIcon;
|
this.copyIcon = copyIcon;
|
||||||
this.copyDoneIconClass = copyDoneIconClass;
|
this.copyDoneIconClass = copyDoneIconClass;
|
||||||
@ -32,24 +32,24 @@ class CopyIcon {
|
|||||||
this.__registerHandlers();
|
this.__registerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
__registerHandlers() {
|
__registerHandlers(): void {
|
||||||
this.copyIcon.addEventListener('click', e => this.copySitekey(e));
|
this.copyIcon.addEventListener("click", (e) => this.copySitekey(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy secret to clipboard
|
* Copy secret to clipboard
|
||||||
*/
|
*/
|
||||||
async copySitekey(e: Event) {
|
async copySitekey(e: Event): Promise<void> {
|
||||||
const image = <HTMLElement>e.target;
|
const image = <HTMLElement>e.target;
|
||||||
const copyDoneIcon = <HTMLElement>(
|
const copyDoneIcon = <HTMLElement>(
|
||||||
image.parentElement.querySelector(`.${this.copyDoneIconClass}`)
|
image.parentElement.querySelector(`.${this.copyDoneIconClass}`)
|
||||||
);
|
);
|
||||||
await navigator.clipboard.writeText(this.writeText);
|
await navigator.clipboard.writeText(this.writeText);
|
||||||
image.style.display = 'none';
|
image.style.display = "none";
|
||||||
copyDoneIcon.style.display = 'block';
|
copyDoneIcon.style.display = "block";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copyDoneIcon.style.display = 'none';
|
copyDoneIcon.style.display = "none";
|
||||||
image.style.display = 'block';
|
image.style.display = "block";
|
||||||
}, 1200);
|
}, 1200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import createError from './index';
|
import createError from "./index";
|
||||||
import * as e from './index';
|
import * as e from "./index";
|
||||||
|
|
||||||
import setup from './setUpTests';
|
import setup from "./setUpTests";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
it('checks if error boxes work', () => {
|
it("checks if error boxes work", () => {
|
||||||
document.body.append(setup());
|
document.body.append(setup());
|
||||||
|
|
||||||
const getMsg = (num: number) => `message ${num}`;
|
const getMsg = (num: number) => `message ${num}`;
|
||||||
@ -32,21 +32,21 @@ it('checks if error boxes work', () => {
|
|||||||
let msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
let msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
expect(msg.innerHTML).toContain(getMsg(1));
|
expect(msg.innerHTML).toContain(getMsg(1));
|
||||||
|
|
||||||
let btn = <HTMLButtonElement>msg.getElementsByClassName(e.ERR_CLOSE)[0];
|
const btn = <HTMLButtonElement>msg.getElementsByClassName(e.ERR_CLOSE)[0];
|
||||||
btn.click();
|
btn.click();
|
||||||
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
expect(msg).toEqual(null);
|
expect(msg).toEqual(null);
|
||||||
|
|
||||||
const errElement = document.createElement('p');
|
const errElement = document.createElement("p");
|
||||||
errElement.appendChild(document.createTextNode(getMsg(2)));
|
errElement.appendChild(document.createTextNode(getMsg(2)));
|
||||||
createError(errElement);
|
createError(errElement);
|
||||||
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector('p');
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector("p");
|
||||||
expect(msg).toEqual(errElement);
|
expect(msg).toEqual(errElement);
|
||||||
|
|
||||||
let timeOutElement = document.createElement('p');
|
const timeOutElement = document.createElement("p");
|
||||||
timeOutElement.appendChild(document.createTextNode(getMsg(2)));
|
timeOutElement.appendChild(document.createTextNode(getMsg(2)));
|
||||||
createError(timeOutElement, 200);
|
createError(timeOutElement, 200);
|
||||||
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector('p');
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector("p");
|
||||||
expect(msg).toEqual(timeOutElement);
|
expect(msg).toEqual(timeOutElement);
|
||||||
jest.runOnlyPendingTimers();
|
jest.runOnlyPendingTimers();
|
||||||
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const ERR_CONTAINER_ID = 'err__container';
|
export const ERR_CONTAINER_ID = "err__container";
|
||||||
export const ERR_MSG_CONTAINER = 'err__msg-container'; // class
|
export const ERR_MSG_CONTAINER = "err__msg-container"; // class
|
||||||
export const ERR_CLOSE = 'err__close'; // class
|
export const ERR_CLOSE = "err__close"; // class
|
||||||
|
|
||||||
export const DEFAULT_LIFETIME = 5000;
|
export const DEFAULT_LIFETIME = 5000;
|
||||||
|
|
||||||
@ -41,11 +41,11 @@ const err = () => {
|
|||||||
const createError = (
|
const createError = (
|
||||||
message: string | HTMLElement,
|
message: string | HTMLElement,
|
||||||
lifetime: number = DEFAULT_LIFETIME,
|
lifetime: number = DEFAULT_LIFETIME,
|
||||||
) => {
|
): void => {
|
||||||
const box = document.createElement('div');
|
const box = document.createElement("div");
|
||||||
|
|
||||||
const msg = () => {
|
const msg = () => {
|
||||||
if (typeof message === 'string') {
|
if (typeof message === "string") {
|
||||||
return document.createTextNode(message);
|
return document.createTextNode(message);
|
||||||
} else {
|
} else {
|
||||||
return message;
|
return message;
|
||||||
@ -55,8 +55,8 @@ const createError = (
|
|||||||
box.className = ERR_MSG_CONTAINER;
|
box.className = ERR_MSG_CONTAINER;
|
||||||
box.appendChild(msg());
|
box.appendChild(msg());
|
||||||
|
|
||||||
const deleteBtn = document.createElement('button');
|
const deleteBtn = document.createElement("button");
|
||||||
const deleteMsg = document.createTextNode('x');
|
const deleteMsg = document.createTextNode("x");
|
||||||
deleteBtn.appendChild(deleteMsg);
|
deleteBtn.appendChild(deleteMsg);
|
||||||
deleteBtn.className = ERR_CLOSE;
|
deleteBtn.className = ERR_CLOSE;
|
||||||
box.appendChild(deleteBtn);
|
box.appendChild(deleteBtn);
|
||||||
@ -71,7 +71,7 @@ const createError = (
|
|||||||
box.remove();
|
box.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteBtn.addEventListener('click', e => deleteHandler(e));
|
deleteBtn.addEventListener("click", e => deleteHandler(e));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createError;
|
export default createError;
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import * as e from './index';
|
import * as e from "./index";
|
||||||
|
|
||||||
const setup = () => {
|
const setup = (): HTMLElement => {
|
||||||
let x = document.createElement('div');
|
const x = document.createElement("div");
|
||||||
x.id = e.ERR_CONTAINER_ID;
|
x.id = e.ERR_CONTAINER_ID;
|
||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const showPasswordButtonClassHidden = 'show-password--hide';
|
const showPasswordButtonClassHidden = "show-password--hide";
|
||||||
const showPasswordButtonClassShowing = 'show-password--show';
|
const showPasswordButtonClassShowing = "show-password--show";
|
||||||
|
|
||||||
const container = 'show-password-container';
|
const container = "show-password-container";
|
||||||
|
|
||||||
let display = 'hidden';
|
let display = "hidden";
|
||||||
|
|
||||||
const showPasswordButtons = () => {
|
const showPasswordButtons = () => {
|
||||||
let buttons: NodeListOf<HTMLElement>;
|
let buttons: NodeListOf<HTMLElement>;
|
||||||
@ -49,45 +49,45 @@ const hidePasswordButtons = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// e is click event from show password container
|
// e is click event from show password container
|
||||||
export const showPassword = () => {
|
export const showPassword = (): void => {
|
||||||
const inputs = document.body.querySelectorAll('input');
|
const inputs = document.body.querySelectorAll("input");
|
||||||
|
|
||||||
if (display == 'hidden') {
|
if (display == "hidden") {
|
||||||
display = 'show';
|
display = "show";
|
||||||
inputs.forEach(element => {
|
inputs.forEach(element => {
|
||||||
if (element.type === 'password') {
|
if (element.type === "password") {
|
||||||
element.type = 'text';
|
element.type = "text";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
showPasswordButtons().forEach((button: HTMLInputElement) => {
|
showPasswordButtons().forEach((button: HTMLInputElement) => {
|
||||||
button.style.display = 'none';
|
button.style.display = "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
hidePasswordButtons().forEach((button: HTMLInputElement) => {
|
hidePasswordButtons().forEach((button: HTMLInputElement) => {
|
||||||
button.style.display = 'inline';
|
button.style.display = "inline";
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
display = 'hidden';
|
display = "hidden";
|
||||||
inputs.forEach(element => {
|
inputs.forEach(element => {
|
||||||
if (element.type === 'text' && element.name.includes('password')) {
|
if (element.type === "text" && element.name.includes("password")) {
|
||||||
element.type = 'password';
|
element.type = "password";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
showPasswordButtons().forEach((button: HTMLInputElement) => {
|
showPasswordButtons().forEach((button: HTMLInputElement) => {
|
||||||
button.style.display = 'inline';
|
button.style.display = "inline";
|
||||||
});
|
});
|
||||||
|
|
||||||
hidePasswordButtons().forEach((button: HTMLInputElement) => {
|
hidePasswordButtons().forEach((button: HTMLInputElement) => {
|
||||||
button.style.display = 'none';
|
button.style.display = "none";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// posibily clicked on something else
|
// posibily clicked on something else
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerShowPassword = () => {
|
export const registerShowPassword = (): void => {
|
||||||
document.querySelectorAll(`.${container}`).forEach(container => {
|
document.querySelectorAll(`.${container}`).forEach(container => {
|
||||||
container.addEventListener('click', showPassword);
|
container.addEventListener("click", showPassword);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import registerShowPassword from './index';
|
import registerShowPassword from "./index";
|
||||||
import {showPassword} from './index';
|
import {showPassword} from "./index";
|
||||||
|
|
||||||
const initial_content = `
|
const initial_content = `
|
||||||
<form class="sitekey-form" method="POST" action="/api/v1/signin" id="form" data-bitwarden-watching="1">
|
<form class="sitekey-form" method="POST" action="/api/v1/signin" id="form" data-bitwarden-watching="1">
|
||||||
@ -41,49 +41,49 @@ const initial_content = `
|
|||||||
</form>
|
</form>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
it('show password works', () => {
|
it("show password works", () => {
|
||||||
document.body.innerHTML = initial_content;
|
document.body.innerHTML = initial_content;
|
||||||
|
|
||||||
const container = <HTMLElement>(
|
const container = <HTMLElement>(
|
||||||
document.querySelector(`.show-password-container`)
|
document.querySelector(".show-password-container")
|
||||||
);
|
);
|
||||||
const hide = <HTMLElement>container.querySelector('.show-password--hide');
|
const hide = <HTMLElement>container.querySelector(".show-password--hide");
|
||||||
const show = <HTMLElement>container.querySelector('.show-password--show');
|
const show = <HTMLElement>container.querySelector(".show-password--show");
|
||||||
const password = <HTMLInputElement>document.getElementById('password');
|
const password = <HTMLInputElement>document.getElementById("password");
|
||||||
show.style.display = 'inline';
|
show.style.display = "inline";
|
||||||
hide.style.display = 'none';
|
hide.style.display = "none";
|
||||||
|
|
||||||
showPassword();
|
showPassword();
|
||||||
expect(hide.style.display).toEqual('inline');
|
expect(hide.style.display).toEqual("inline");
|
||||||
expect(show.style.display).toEqual('none');
|
expect(show.style.display).toEqual("none");
|
||||||
expect(password.type).toEqual('text');
|
expect(password.type).toEqual("text");
|
||||||
|
|
||||||
showPassword();
|
showPassword();
|
||||||
expect(show.style.display).toEqual('inline');
|
expect(show.style.display).toEqual("inline");
|
||||||
expect(hide.style.display).toEqual('none');
|
expect(hide.style.display).toEqual("none");
|
||||||
expect(password.type).toEqual('password');
|
expect(password.type).toEqual("password");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show password click works', () => {
|
it("show password click works", () => {
|
||||||
document.body.innerHTML = initial_content;
|
document.body.innerHTML = initial_content;
|
||||||
|
|
||||||
const container = <HTMLElement>(
|
const container = <HTMLElement>(
|
||||||
document.querySelector(`.show-password-container`)
|
document.querySelector(".show-password-container")
|
||||||
);
|
);
|
||||||
const hide = <HTMLElement>container.querySelector('.show-password--hide');
|
const hide = <HTMLElement>container.querySelector(".show-password--hide");
|
||||||
const show = <HTMLElement>container.querySelector('.show-password--show');
|
const show = <HTMLElement>container.querySelector(".show-password--show");
|
||||||
const password = <HTMLInputElement>document.getElementById('password');
|
const password = <HTMLInputElement>document.getElementById("password");
|
||||||
show.style.display = 'inline';
|
show.style.display = "inline";
|
||||||
hide.style.display = 'none';
|
hide.style.display = "none";
|
||||||
|
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
container.click();
|
container.click();
|
||||||
expect(hide.style.display).toEqual('inline');
|
expect(hide.style.display).toEqual("inline");
|
||||||
expect(show.style.display).toEqual('none');
|
expect(show.style.display).toEqual("none");
|
||||||
expect(password.type).toEqual('text');
|
expect(password.type).toEqual("text");
|
||||||
|
|
||||||
container.click();
|
container.click();
|
||||||
expect(show.style.display).toEqual('inline');
|
expect(show.style.display).toEqual("inline");
|
||||||
expect(hide.style.display).toEqual('none');
|
expect(hide.style.display).toEqual("none");
|
||||||
expect(password.type).toEqual('password');
|
expect(password.type).toEqual("password");
|
||||||
});
|
});
|
||||||
|
@ -15,39 +15,39 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Router} from './router';
|
import {Router} from "./router";
|
||||||
|
|
||||||
import * as login from './auth/login/ts/';
|
import * as login from "./auth/login/ts/";
|
||||||
import * as register from './auth/register/ts/';
|
import * as register from "./auth/register/ts/";
|
||||||
import * as panel from './panel/ts/index';
|
import * as panel from "./panel/ts/index";
|
||||||
import settings from './panel/settings/';
|
import settings from "./panel/settings/";
|
||||||
import * as deleteAccount from './panel/settings/account/delete';
|
import * as deleteAccount from "./panel/settings/account/delete";
|
||||||
import * as updateSecret from './panel/settings/secret/update';
|
import * as updateSecret from "./panel/settings/secret/update";
|
||||||
import * as addSiteKey from './panel/sitekey/add/ts';
|
import * as addSiteKey from "./panel/sitekey/add/ts";
|
||||||
import * as editSitekey from './panel/sitekey/edit/';
|
import * as editSitekey from "./panel/sitekey/edit/";
|
||||||
import * as deleteSitekey from './panel/sitekey/delete/';
|
import * as deleteSitekey from "./panel/sitekey/delete/";
|
||||||
import * as listSitekeys from './panel/sitekey/list/ts';
|
import * as listSitekeys from "./panel/sitekey/list/ts";
|
||||||
import * as notidications from './panel/notifications/ts';
|
import * as notidications from "./panel/notifications/ts";
|
||||||
import {MODE} from './logger';
|
import {MODE} from "./logger";
|
||||||
import log from './logger';
|
import log from "./logger";
|
||||||
|
|
||||||
import VIEWS from './views/v1/routes';
|
import VIEWS from "./views/v1/routes";
|
||||||
|
|
||||||
import './main.scss';
|
import "./main.scss";
|
||||||
import './auth/css/main.scss';
|
import "./auth/css/main.scss";
|
||||||
import './components/details-footer/main.scss';
|
import "./components/details-footer/main.scss";
|
||||||
import './components/error/main.scss';
|
import "./components/error/main.scss";
|
||||||
import './components/showPassword/main.scss';
|
import "./components/showPassword/main.scss";
|
||||||
import './panel/css/main.scss';
|
import "./panel/css/main.scss";
|
||||||
import './panel/navbar/main.scss';
|
import "./panel/navbar/main.scss";
|
||||||
import './panel/settings/main.scss';
|
import "./panel/settings/main.scss";
|
||||||
import './panel/notifications/main.scss';
|
import "./panel/notifications/main.scss";
|
||||||
import './panel/header/taskbar/main.scss';
|
import "./panel/header/taskbar/main.scss";
|
||||||
import './panel/help-banner/main.scss';
|
import "./panel/help-banner/main.scss";
|
||||||
import './panel/sitekey/add/css/main.scss';
|
import "./panel/sitekey/add/css/main.scss";
|
||||||
import './panel/sitekey/list/css/main.scss';
|
import "./panel/sitekey/list/css/main.scss";
|
||||||
|
|
||||||
import './errors/main.scss';
|
import "./errors/main.scss";
|
||||||
|
|
||||||
log.setMode(MODE.production);
|
log.setMode(MODE.production);
|
||||||
|
|
||||||
@ -62,8 +62,8 @@ router.register(VIEWS.loginUser, login.index);
|
|||||||
router.register(VIEWS.notifications, notidications.index);
|
router.register(VIEWS.notifications, notidications.index);
|
||||||
router.register(VIEWS.listSitekey, listSitekeys.index);
|
router.register(VIEWS.listSitekey, listSitekeys.index);
|
||||||
router.register(VIEWS.addSiteKey, addSiteKey.index);
|
router.register(VIEWS.addSiteKey, addSiteKey.index);
|
||||||
router.register(VIEWS.editSitekey('[A-Z),a-z,0-9]+'), editSitekey.index);
|
router.register(VIEWS.editSitekey("[A-Z),a-z,0-9]+"), editSitekey.index);
|
||||||
router.register(VIEWS.deleteSitekey('[A-Z),a-z,0-9]+'), deleteSitekey.index);
|
router.register(VIEWS.deleteSitekey("[A-Z),a-z,0-9]+"), deleteSitekey.index);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
router.route();
|
router.route();
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './mobile.scss';
|
import "./mobile.scss";
|
||||||
import './auth/css/mobile.scss';
|
import "./auth/css/mobile.scss";
|
||||||
import './components/details-footer/mobile.scss';
|
import "./components/details-footer/mobile.scss";
|
||||||
import './panel/css/mobile.scss';
|
import "./panel/css/mobile.scss";
|
||||||
import './panel/settings/mobile.scss';
|
import "./panel/settings/mobile.scss";
|
||||||
import './panel/header/taskbar/mobile.scss';
|
import "./panel/header/taskbar/mobile.scss";
|
||||||
import './panel/navbar/mobile.scss';
|
import "./panel/navbar/mobile.scss";
|
||||||
import './panel/help-banner/mobile.scss';
|
import "./panel/help-banner/mobile.scss";
|
||||||
import './panel/sitekey/add/css/mobile.scss';
|
import "./panel/sitekey/add/css/mobile.scss";
|
||||||
import './panel/sitekey/list/css/mobile.scss';
|
import "./panel/sitekey/list/css/mobile.scss";
|
||||||
|
@ -14,4 +14,4 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import './main.scss';
|
import "./main.scss";
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error';
|
import createError from "../../../components/error";
|
||||||
|
|
||||||
import ROUTES from '../../../api/v1/routes';
|
import ROUTES from "../../../api/v1/routes";
|
||||||
|
|
||||||
const BTN = document.querySelectorAll('.notification__mark-read-btn');
|
const BTN = document.querySelectorAll(".notification__mark-read-btn");
|
||||||
const TABLE_BODY = document.querySelector('.notification__body');
|
const TABLE_BODY = document.querySelector(".notification__body");
|
||||||
|
|
||||||
const notification_record = (id: number) =>
|
const notification_record = (id: number) =>
|
||||||
<HTMLElement>TABLE_BODY.querySelector(`#notification__item-${id}`);
|
<HTMLElement>TABLE_BODY.querySelector(`#notification__item-${id}`);
|
||||||
@ -46,10 +46,10 @@ const markRead = async (e: Event) => {
|
|||||||
|
|
||||||
const addMarkReadEventListenet = () => {
|
const addMarkReadEventListenet = () => {
|
||||||
BTN.forEach(btn => {
|
BTN.forEach(btn => {
|
||||||
btn.addEventListener('click', markRead, true);
|
btn.addEventListener("click", markRead, true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
addMarkReadEventListenet();
|
addMarkReadEventListenet();
|
||||||
};
|
};
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getPassword} from '../../../auth/login/ts/';
|
import {getPassword} from "../../../auth/login/ts/";
|
||||||
import FORM from '../../../auth/sudo/';
|
import FORM from "../../../auth/sudo/";
|
||||||
|
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error';
|
import createError from "../../../components/error";
|
||||||
import registerShowPassword from '../../../components/showPassword';
|
import registerShowPassword from "../../../components/showPassword";
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
const submit = async (e: Event) => {
|
const submit = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -44,7 +44,7 @@ const submit = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
FORM.get().addEventListener('submit', submit, true);
|
FORM.get().addEventListener("submit", submit, true);
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
};
|
};
|
||||||
|
@ -15,28 +15,28 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import registerShowPassword from '../../components/showPassword/';
|
import registerShowPassword from "../../components/showPassword/";
|
||||||
import CopyIcon from '../../components/clipboard/';
|
import CopyIcon from "../../components/clipboard/";
|
||||||
import createError from '../../components/error/';
|
import createError from "../../components/error/";
|
||||||
|
|
||||||
import emailExists from '../../auth/register/ts/emailExists';
|
import emailExists from "../../auth/register/ts/emailExists";
|
||||||
import userExists from '../../auth/register/ts/userExists';
|
import userExists from "../../auth/register/ts/userExists";
|
||||||
|
|
||||||
import LazyElement from '../../utils/lazyElement';
|
import LazyElement from "../../utils/lazyElement";
|
||||||
import isBlankString from '../../utils/isBlankString';
|
import isBlankString from "../../utils/isBlankString";
|
||||||
import getFormUrl from '../../utils/getFormUrl';
|
import getFormUrl from "../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../utils/genJsonPayload';
|
import genJsonPayload from "../../utils/genJsonPayload";
|
||||||
|
|
||||||
import VIEWS from '../../views/v1/routes';
|
import VIEWS from "../../views/v1/routes";
|
||||||
|
|
||||||
const SECRET_COPY_ICON = 'settings__secret-copy';
|
const SECRET_COPY_ICON = "settings__secret-copy";
|
||||||
const SECRET_COPY_DONE_ICON = 'settings__secret-copy-done';
|
const SECRET_COPY_DONE_ICON = "settings__secret-copy-done";
|
||||||
|
|
||||||
// form IDs
|
// form IDs
|
||||||
const DELETE_FORM = 'settings__delete-form';
|
const DELETE_FORM = "settings__delete-form";
|
||||||
const EMAIL_FORM = 'settings__email-form';
|
const EMAIL_FORM = "settings__email-form";
|
||||||
const USERNAME_FORM = 'settings__username-form';
|
const USERNAME_FORM = "settings__username-form";
|
||||||
const SECRET_FORM = 'settings__secret-form';
|
const SECRET_FORM = "settings__secret-form";
|
||||||
|
|
||||||
// form elements
|
// form elements
|
||||||
const deleteForm = new LazyElement(DELETE_FORM);
|
const deleteForm = new LazyElement(DELETE_FORM);
|
||||||
@ -45,8 +45,8 @@ const usernameForm = new LazyElement(USERNAME_FORM);
|
|||||||
const secretForm = new LazyElement(SECRET_FORM);
|
const secretForm = new LazyElement(SECRET_FORM);
|
||||||
|
|
||||||
// field IDs
|
// field IDs
|
||||||
const EMAIL = 'email';
|
const EMAIL = "email";
|
||||||
const USERNAME = 'username';
|
const USERNAME = "username";
|
||||||
|
|
||||||
// field elements
|
// field elements
|
||||||
const emailField = new LazyElement(EMAIL);
|
const emailField = new LazyElement(EMAIL);
|
||||||
@ -57,7 +57,7 @@ const updateEmail = async (e: Event) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const emailElement = <HTMLInputElement>emailField.get();
|
const emailElement = <HTMLInputElement>emailField.get();
|
||||||
const email = emailElement.value;
|
const email = emailElement.value;
|
||||||
isBlankString(email, 'email', e);
|
isBlankString(email, "email", e);
|
||||||
if (await emailExists(emailElement)) {
|
if (await emailExists(emailElement)) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -80,7 +80,7 @@ const updateUsername = async (e: Event) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const usernameElement = <HTMLInputElement>usernameField.get();
|
const usernameElement = <HTMLInputElement>usernameField.get();
|
||||||
const username = usernameElement.value;
|
const username = usernameElement.value;
|
||||||
isBlankString(username, 'username', e);
|
isBlankString(username, "username", e);
|
||||||
if (await userExists(usernameElement)) {
|
if (await userExists(usernameElement)) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -101,7 +101,7 @@ const updateUsername = async (e: Event) => {
|
|||||||
const updateSecret = (e: Event) => {
|
const updateSecret = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const msg =
|
const msg =
|
||||||
'WARNING: updating secret will cause service disruption if old secret is still in use post update';
|
"WARNING: updating secret will cause service disruption if old secret is still in use post update";
|
||||||
if (confirm(msg)) {
|
if (confirm(msg)) {
|
||||||
window.location.assign(VIEWS.updateSecret);
|
window.location.assign(VIEWS.updateSecret);
|
||||||
}
|
}
|
||||||
@ -118,14 +118,14 @@ const deleteAccount = (e: Event) => {
|
|||||||
|
|
||||||
// regist form event handlers
|
// regist form event handlers
|
||||||
const registerForms = () => {
|
const registerForms = () => {
|
||||||
deleteForm.get().addEventListener('submit', e => deleteAccount(e), true);
|
deleteForm.get().addEventListener("submit", (e) => deleteAccount(e), true);
|
||||||
emailForm.get().addEventListener('submit', e => updateEmail(e), true);
|
emailForm.get().addEventListener("submit", (e) => updateEmail(e), true);
|
||||||
usernameForm.get().addEventListener('submit', e => updateUsername(e), true);
|
usernameForm.get().addEventListener("submit", (e) => updateUsername(e), true);
|
||||||
console.log(usernameField.get());
|
console.log(usernameField.get());
|
||||||
usernameField
|
usernameField
|
||||||
.get()
|
.get()
|
||||||
.addEventListener('input', async () => await userExists(), false);
|
.addEventListener("input", async () => await userExists(), false);
|
||||||
secretForm.get().addEventListener('submit', e => updateSecret(e), true);
|
secretForm.get().addEventListener("submit", (e) => updateSecret(e), true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// set up copying account secret to clipboard
|
// set up copying account secret to clipboard
|
||||||
@ -138,7 +138,7 @@ const initCopySecret = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// TODO email update button should only change if email value has been changed
|
/// TODO email update button should only change if email value has been changed
|
||||||
const index = () => {
|
const index = (): void => {
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
initCopySecret();
|
initCopySecret();
|
||||||
registerForms();
|
registerForms();
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getPassword} from '../../../auth/login/ts/';
|
import {getPassword} from "../../../auth/login/ts/";
|
||||||
import FORM from '../../../auth/sudo/';
|
import FORM from "../../../auth/sudo/";
|
||||||
|
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error';
|
import createError from "../../../components/error";
|
||||||
import registerShowPassword from '../../../components/showPassword';
|
import registerShowPassword from "../../../components/showPassword";
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
const submit = async (e: Event) => {
|
const submit = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -44,7 +44,7 @@ const submit = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
FORM.get().addEventListener('submit', submit, true);
|
FORM.get().addEventListener("submit", submit, true);
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
};
|
};
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from './levels/getNumLevels';
|
import getNumLevels from "./levels/getNumLevels";
|
||||||
import {getAddForm, trim, addLevel} from './setupTests';
|
import {getAddForm, trim, addLevel} from "./setupTests";
|
||||||
import setup from '../../../../components/error/setUpTests';
|
import setup from "../../../../components/error/setUpTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
document.body.appendChild(setup());
|
document.body.appendChild(setup());
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
it('addLevelButton works', () => {
|
it("addLevelButton works", () => {
|
||||||
expect(getNumLevels()).toBe(1);
|
expect(getNumLevels()).toBe(1);
|
||||||
// add a level
|
// add a level
|
||||||
addLevel(2, 4);
|
addLevel(2, 4);
|
||||||
@ -36,7 +36,7 @@ it('addLevelButton works', () => {
|
|||||||
addLevel(4, 9);
|
addLevel(4, 9);
|
||||||
expect(getNumLevels()).toBe(3);
|
expect(getNumLevels()).toBe(3);
|
||||||
|
|
||||||
let a = document.body.innerHTML;
|
const a = document.body.innerHTML;
|
||||||
|
|
||||||
|
|
||||||
expect(trim(a)).toBe(trim(finalHtml()));
|
expect(trim(a)).toBe(trim(finalHtml()));
|
||||||
|
@ -14,16 +14,16 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import validateLevel from './levels/validateLevel';
|
import validateLevel from "./levels/validateLevel";
|
||||||
import getNumLevels from './levels/getNumLevels';
|
import getNumLevels from "./levels/getNumLevels";
|
||||||
import * as UpdateLevel from './levels/updateLevel';
|
import * as UpdateLevel from "./levels/updateLevel";
|
||||||
import {
|
import {
|
||||||
getRemoveButtonHTML,
|
getRemoveButtonHTML,
|
||||||
addRemoveLevelButtonEventListener,
|
addRemoveLevelButtonEventListener,
|
||||||
} from './removeLevelButton';
|
} from "./removeLevelButton";
|
||||||
import CONST from './const';
|
import CONST from "./const";
|
||||||
|
|
||||||
import log from '../../../../logger';
|
import log from "../../../../logger";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets executed when 'Add' Button is clicked to add levels
|
* Gets executed when 'Add' Button is clicked to add levels
|
||||||
@ -39,30 +39,30 @@ const addLevel = (e: Event) => {
|
|||||||
const isValid = validateLevel(onScreenLevel);
|
const isValid = validateLevel(onScreenLevel);
|
||||||
log.debug(`[addLevelButton] isValid: ${isValid}`);
|
log.debug(`[addLevelButton] isValid: ${isValid}`);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
let error = `Aborting level ${onScreenLevel} addition`;
|
const error = `Aborting level ${onScreenLevel} addition`;
|
||||||
return log.error(error);
|
return log.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
FIELDSET.replaceChild(getRemoveButtonHTML(onScreenLevel), PARENT);
|
FIELDSET.replaceChild(getRemoveButtonHTML(onScreenLevel), PARENT);
|
||||||
|
|
||||||
const newLevelElement = getHtml(onScreenLevel + 1);
|
const newLevelElement = getHtml(onScreenLevel + 1);
|
||||||
FIELDSET.insertAdjacentElement('afterend', newLevelElement);
|
FIELDSET.insertAdjacentElement("afterend", newLevelElement);
|
||||||
UpdateLevel.register(onScreenLevel);
|
UpdateLevel.register(onScreenLevel);
|
||||||
|
|
||||||
addRemoveLevelButtonEventListener(onScreenLevel);
|
addRemoveLevelButtonEventListener(onScreenLevel);
|
||||||
addLevelButtonAddEventListener();
|
addLevelButtonAddEventListener();
|
||||||
const main = document.querySelector('body');
|
const main = document.querySelector("body");
|
||||||
const style = main.style.display;
|
const style = main.style.display;
|
||||||
main.style.display = 'none';
|
main.style.display = "none";
|
||||||
main.style.display = style;
|
main.style.display = style;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** adds onclick event listener */
|
/** adds onclick event listener */
|
||||||
const addLevelButtonAddEventListener = () => {
|
const addLevelButtonAddEventListener = (): void => {
|
||||||
const addLevelButton = <HTMLElement>(
|
const addLevelButton = <HTMLElement>(
|
||||||
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
|
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
|
||||||
);
|
);
|
||||||
addLevelButton.addEventListener('click', addLevel);
|
addLevelButton.addEventListener("click", addLevel);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,25 +72,25 @@ const addLevelButtonAddEventListener = () => {
|
|||||||
const getHtml = (level: number) => {
|
const getHtml = (level: number) => {
|
||||||
log.debug(`[generating HTML getHtml]level: ${level}`);
|
log.debug(`[generating HTML getHtml]level: ${level}`);
|
||||||
|
|
||||||
const fieldset = document.createElement('fieldset'); // new HTMLFieldSetElement();
|
const fieldset = document.createElement("fieldset"); // new HTMLFieldSetElement();
|
||||||
fieldset.className = CONST.LEVEL_CONTAINER_CLASS;
|
fieldset.className = CONST.LEVEL_CONTAINER_CLASS;
|
||||||
fieldset.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`;
|
fieldset.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`;
|
||||||
|
|
||||||
const legend = document.createElement('legend'); // new HTMLLegendElement();
|
const legend = document.createElement("legend"); // new HTMLLegendElement();
|
||||||
legend.className = CONST.LEGEND_CLASS;
|
legend.className = CONST.LEGEND_CLASS;
|
||||||
const legendText = document.createTextNode(`Level ${level}`);
|
const legendText = document.createTextNode(`Level ${level}`);
|
||||||
legend.appendChild(legendText);
|
legend.appendChild(legendText);
|
||||||
|
|
||||||
fieldset.appendChild(legend);
|
fieldset.appendChild(legend);
|
||||||
|
|
||||||
const vistitorLabel = document.createElement('label'); //document.createElement('label');
|
const vistitorLabel = document.createElement("label"); //document.createElement('label');
|
||||||
vistitorLabel.className = CONST.LABEL_CLASS;
|
vistitorLabel.className = CONST.LABEL_CLASS;
|
||||||
const visitorText = document.createTextNode('Visitor');
|
const visitorText = document.createTextNode("Visitor");
|
||||||
vistitorLabel.appendChild(visitorText);
|
vistitorLabel.appendChild(visitorText);
|
||||||
const visitor = document.createElement('input'); //document.createElement('input');
|
const visitor = document.createElement("input"); //document.createElement('input');
|
||||||
const visitorId = `${CONST.VISITOR_WITHOUT_LEVEL}${level}`;
|
const visitorId = `${CONST.VISITOR_WITHOUT_LEVEL}${level}`;
|
||||||
visitor.className = CONST.LEVEL_INPUT_CLASS;
|
visitor.className = CONST.LEVEL_INPUT_CLASS;
|
||||||
visitor.type = 'number';
|
visitor.type = "number";
|
||||||
visitor.name = visitorId;
|
visitor.name = visitorId;
|
||||||
visitor.id = visitorId;
|
visitor.id = visitorId;
|
||||||
vistitorLabel.htmlFor = visitorId;
|
vistitorLabel.htmlFor = visitorId;
|
||||||
@ -98,13 +98,13 @@ const getHtml = (level: number) => {
|
|||||||
|
|
||||||
fieldset.appendChild(vistitorLabel);
|
fieldset.appendChild(vistitorLabel);
|
||||||
|
|
||||||
const difficultyLabel = document.createElement('label');
|
const difficultyLabel = document.createElement("label");
|
||||||
difficultyLabel.className = CONST.LABEL_CLASS;
|
difficultyLabel.className = CONST.LABEL_CLASS;
|
||||||
const difficultyText = document.createTextNode('Difficulty');
|
const difficultyText = document.createTextNode("Difficulty");
|
||||||
difficultyLabel.appendChild(difficultyText);
|
difficultyLabel.appendChild(difficultyText);
|
||||||
const difficulty = document.createElement('input');
|
const difficulty = document.createElement("input");
|
||||||
const difficultyID = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${level}`;
|
const difficultyID = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${level}`;
|
||||||
difficulty.type = 'number';
|
difficulty.type = "number";
|
||||||
difficulty.name = difficultyID;
|
difficulty.name = difficultyID;
|
||||||
difficulty.className = CONST.LEVEL_INPUT_CLASS;
|
difficulty.className = CONST.LEVEL_INPUT_CLASS;
|
||||||
difficulty.id = difficultyID;
|
difficulty.id = difficultyID;
|
||||||
@ -113,18 +113,18 @@ const getHtml = (level: number) => {
|
|||||||
|
|
||||||
fieldset.appendChild(difficultyLabel);
|
fieldset.appendChild(difficultyLabel);
|
||||||
|
|
||||||
const addLevelLabel = document.createElement('label');
|
const addLevelLabel = document.createElement("label");
|
||||||
addLevelLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
|
addLevelLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
|
||||||
const addLevel = document.createElement('input');
|
const addLevel = document.createElement("input");
|
||||||
addLevel.className = CONST.ADD_LEVEL_BUTTON;
|
addLevel.className = CONST.ADD_LEVEL_BUTTON;
|
||||||
addLevel.type = 'button';
|
addLevel.type = "button";
|
||||||
const addLevelButtonID = 'add';
|
const addLevelButtonID = "add";
|
||||||
addLevel.name = addLevelButtonID;
|
addLevel.name = addLevelButtonID;
|
||||||
addLevel.id = addLevelButtonID;
|
addLevel.id = addLevelButtonID;
|
||||||
addLevelLabel.htmlFor = addLevelButtonID;
|
addLevelLabel.htmlFor = addLevelButtonID;
|
||||||
const addText = document.createTextNode('Add level');
|
const addText = document.createTextNode("Add level");
|
||||||
addLevelLabel.appendChild(addText);
|
addLevelLabel.appendChild(addText);
|
||||||
addLevel.value = 'Add';
|
addLevel.value = "Add";
|
||||||
addLevelLabel.appendChild(addLevel);
|
addLevelLabel.appendChild(addLevel);
|
||||||
|
|
||||||
fieldset.appendChild(addLevelLabel);
|
fieldset.appendChild(addLevelLabel);
|
||||||
|
@ -15,25 +15,25 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const LABEL_INNER_TEXT_WITHOUT_LEVEL = 'Level ';
|
const LABEL_INNER_TEXT_WITHOUT_LEVEL = "Level ";
|
||||||
const LABEL_CLASS = 'sitekey-form__level-label';
|
const LABEL_CLASS = "sitekey-form__level-label";
|
||||||
|
|
||||||
const INPUT_ID_WITHOUT_LEVEL = 'level';
|
const INPUT_ID_WITHOUT_LEVEL = "level";
|
||||||
const LEVEL_INPUT_CLASS = 'sitekey-form__level-input';
|
const LEVEL_INPUT_CLASS = "sitekey-form__level-input";
|
||||||
|
|
||||||
const VISITOR_WITHOUT_LEVEL = 'visitor';
|
const VISITOR_WITHOUT_LEVEL = "visitor";
|
||||||
const DIFFICULTY_WITHOUT_LEVEL = 'difficulty';
|
const DIFFICULTY_WITHOUT_LEVEL = "difficulty";
|
||||||
|
|
||||||
const LEVEL_CONTAINER_CLASS = 'sitekey__level-container';
|
const LEVEL_CONTAINER_CLASS = "sitekey__level-container";
|
||||||
const LEVEL_FIELDSET_ID_WITHOUT_LEVEL = 'level-group-';
|
const LEVEL_FIELDSET_ID_WITHOUT_LEVEL = "level-group-";
|
||||||
const LEGEND_CLASS = 'sitekey__level-title';
|
const LEGEND_CLASS = "sitekey__level-title";
|
||||||
|
|
||||||
const REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL = 'remove-level';
|
const REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL = "remove-level";
|
||||||
const REMOVE_LEVEL_BUTTON_CLASS = 'sitekey-form__level-remove-level-button';
|
const REMOVE_LEVEL_BUTTON_CLASS = "sitekey-form__level-remove-level-button";
|
||||||
const REMOVE_LEVEL_LABEL_TEXT = 'Remove Level';
|
const REMOVE_LEVEL_LABEL_TEXT = "Remove Level";
|
||||||
const REMOVE_LEVEL_LABEL_CLASS = 'sitekey-form__level-label--hidden';
|
const REMOVE_LEVEL_LABEL_CLASS = "sitekey-form__level-label--hidden";
|
||||||
|
|
||||||
const ADD_LEVEL_BUTTON = 'sitekey-form__level-add-level-button';
|
const ADD_LEVEL_BUTTON = "sitekey-form__level-add-level-button";
|
||||||
|
|
||||||
const CONST = {
|
const CONST = {
|
||||||
LABEL_CLASS,
|
LABEL_CLASS,
|
||||||
|
@ -15,30 +15,31 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LEVELS} from '../levels';
|
import { LEVELS } from "../levels";
|
||||||
|
|
||||||
import getFormUrl from '../../../../../utils/getFormUrl';
|
import getFormUrl from "../../../../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../../../utils/genJsonPayload";
|
||||||
|
|
||||||
import VIEWS from '../../../../../views/v1/routes';
|
import VIEWS from "../../../../../views/v1/routes";
|
||||||
|
|
||||||
import validateDescription from './validateDescription';
|
import validateDescription from "./validateDescription";
|
||||||
import validateDuration from './validateDuration';
|
import validateDuration from "./validateDuration";
|
||||||
|
|
||||||
import createError from '../../../../../components/error';
|
import createError from "../../../../../components/error";
|
||||||
|
|
||||||
export const SITE_KEY_FORM_CLASS = 'sitekey-form';
|
export const SITE_KEY_FORM_CLASS = "sitekey-form";
|
||||||
export const FORM = <HTMLFormElement>document.querySelector(`.${SITE_KEY_FORM_CLASS}`);
|
export const FORM = <HTMLFormElement>(
|
||||||
|
document.querySelector(`.${SITE_KEY_FORM_CLASS}`)
|
||||||
|
);
|
||||||
|
|
||||||
export const addSubmitEventListener = () => {
|
export const addSubmitEventListener = (): void =>
|
||||||
FORM.addEventListener('submit', submit, true);
|
FORM.addEventListener("submit", submit, true);
|
||||||
};
|
|
||||||
|
|
||||||
const submit = async (e: Event) => {
|
const submit = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const description = validateDescription(e);
|
const description = validateDescription(e);
|
||||||
const duration = validateDuration(e);
|
const duration = validateDuration();
|
||||||
|
|
||||||
const formUrl = getFormUrl(FORM);
|
const formUrl = getFormUrl(FORM);
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import validateDescription from './validateDescription';
|
import validateDescription from "./validateDescription";
|
||||||
import {getAddForm, fillDescription} from '../setupTests';
|
import {getAddForm, fillDescription} from "../setupTests";
|
||||||
import {mockAlert} from '../../../../../setUpTests';
|
import {mockAlert} from "../../../../../setUpTests";
|
||||||
|
|
||||||
import setup from '../../../../../components/error/setUpTests';
|
import setup from "../../../../../components/error/setUpTests";
|
||||||
|
|
||||||
mockAlert();
|
mockAlert();
|
||||||
|
|
||||||
@ -27,17 +27,17 @@ document.body.innerHTML = getAddForm();
|
|||||||
|
|
||||||
const emptyErr = "can't be empty";
|
const emptyErr = "can't be empty";
|
||||||
|
|
||||||
it('validateDescription workds', () => {
|
it("validateDescription workds", () => {
|
||||||
document.querySelector('body').appendChild(setup());
|
document.querySelector("body").appendChild(setup());
|
||||||
try {
|
try {
|
||||||
const event = new Event('submit');
|
const event = new Event("submit");
|
||||||
validateDescription(event);
|
validateDescription(event);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(emptyErr);
|
expect(e.message).toContain(emptyErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill and validate
|
// fill and validate
|
||||||
fillDescription('testing');
|
fillDescription("testing");
|
||||||
const event = new Event('submit');
|
const event = new Event("submit");
|
||||||
validateDescription(event);
|
validateDescription(event);
|
||||||
});
|
});
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import isBlankString from '../../../../../utils/isBlankString';
|
import isBlankString from "../../../../../utils/isBlankString";
|
||||||
|
|
||||||
const validateDescription = (e: Event) => {
|
const validateDescription = (e: Event): string => {
|
||||||
const inputElement = <HTMLInputElement>document.getElementById('description');
|
const inputElement = <HTMLInputElement>document.getElementById("description");
|
||||||
const val = inputElement.value;
|
const val = inputElement.value;
|
||||||
const filed = 'Description';
|
const filed = "Description";
|
||||||
isBlankString(val, filed, e);
|
isBlankString(val, filed, e);
|
||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import isNumber from '../../../../../utils/isNumber';
|
|
||||||
|
|
||||||
//const validateDuration = (e: Event) => {
|
//const validateDuration = (e: Event) => {
|
||||||
// const duartionElement = <HTMLInputElement>document.getElementById('duration');
|
// const duartionElement = <HTMLInputElement>document.getElementById('duration');
|
||||||
// const duration = parseInt(duartionElement.value);
|
// const duration = parseInt(duartionElement.value);
|
||||||
@ -31,30 +29,28 @@ import isNumber from '../../../../../utils/isNumber';
|
|||||||
//
|
//
|
||||||
//export default validateDuration;
|
//export default validateDuration;
|
||||||
|
|
||||||
import validateDuration from './validateDuration';
|
import validateDuration from "./validateDuration";
|
||||||
import {getAddForm, fillDuration} from '../setupTests';
|
import {getAddForm, fillDuration} from "../setupTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
const emptyErr = "can't be empty";
|
const emptyErr = "can't be empty";
|
||||||
const NaNErr = 'duration can contain nubers only';
|
const NaNErr = "duration can contain nubers only";
|
||||||
const zeroErr = 'duration must be greater than zero';
|
const zeroErr = "duration must be greater than zero";
|
||||||
|
|
||||||
const duration = 30;
|
const duration = 30;
|
||||||
|
|
||||||
it('validateDuration workds', () => {
|
it("validateDuration workds", () => {
|
||||||
try {
|
try {
|
||||||
const event = new Event('submit');
|
validateDuration();
|
||||||
validateDuration(event);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(emptyErr);
|
expect(e.message).toContain(emptyErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill string error
|
// fill string error
|
||||||
try {
|
try {
|
||||||
fillDuration('testing');
|
fillDuration("testing");
|
||||||
const event = new Event('submit');
|
validateDuration();
|
||||||
validateDuration(event);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(NaNErr);
|
expect(e.message).toContain(NaNErr);
|
||||||
}
|
}
|
||||||
@ -62,13 +58,11 @@ it('validateDuration workds', () => {
|
|||||||
// zero err
|
// zero err
|
||||||
try {
|
try {
|
||||||
fillDuration(0);
|
fillDuration(0);
|
||||||
const event = new Event('submit');
|
validateDuration();
|
||||||
validateDuration(event);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(zeroErr);
|
expect(e.message).toContain(zeroErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fillDuration(duration);
|
fillDuration(duration);
|
||||||
const event = new Event('submit');
|
expect(validateDuration()).toBe(duration);
|
||||||
expect(validateDuration(event)).toBe(duration);
|
|
||||||
});
|
});
|
||||||
|
@ -14,17 +14,17 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import isNumber from '../../../../../utils/isNumber';
|
import isNumber from "../../../../../utils/isNumber";
|
||||||
|
|
||||||
const validateDuration = (e: Event) => {
|
const validateDuration = (): number => {
|
||||||
const duartionElement = <HTMLInputElement>document.getElementById('duration');
|
const duartionElement = <HTMLInputElement>document.getElementById("duration");
|
||||||
const duration = parseInt(duartionElement.value);
|
const duration = parseInt(duartionElement.value);
|
||||||
if (!isNumber(duration) || Number.isNaN(duration)) {
|
if (!isNumber(duration) || Number.isNaN(duration)) {
|
||||||
throw new Error('duration can contain nubers only');
|
throw new Error("duration can contain nubers only");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duration <= 0) {
|
if (duration <= 0) {
|
||||||
throw new Error('duration must be greater than zero');
|
throw new Error("duration must be greater than zero");
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
};
|
};
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import addLevelButtonAddEventListener from './addLevelButton';
|
import addLevelButtonAddEventListener from "./addLevelButton";
|
||||||
import addSubmitEventListener from './form';
|
import addSubmitEventListener from "./form";
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
addLevelButtonAddEventListener();
|
addLevelButtonAddEventListener();
|
||||||
addSubmitEventListener();
|
addSubmitEventListener();
|
||||||
};
|
};
|
||||||
|
@ -15,27 +15,27 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getLevelFields from './getLevelFields';
|
import getLevelFields from "./getLevelFields";
|
||||||
import {
|
import {
|
||||||
getAddForm,
|
getAddForm,
|
||||||
level1,
|
level1,
|
||||||
level2,
|
level2,
|
||||||
fillAddLevel,
|
fillAddLevel,
|
||||||
addLevel,
|
addLevel,
|
||||||
} from '../setupTests';
|
} from "../setupTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
const visNumErr = 'visitor can contain nubers only';
|
const visNumErr = "visitor can contain nubers only";
|
||||||
const diffNumErr = 'difficulty can contain nubers only';
|
const diffNumErr = "difficulty can contain nubers only";
|
||||||
|
|
||||||
it('get levels fields works', () => {
|
it("get levels fields works", () => {
|
||||||
addLevel(level1.visitor_threshold, level1.difficulty_factor);
|
addLevel(level1.visitor_threshold, level1.difficulty_factor);
|
||||||
expect(getLevelFields(1)).toEqual(level1);
|
expect(getLevelFields(1)).toEqual(level1);
|
||||||
|
|
||||||
// NaN visitor
|
// NaN visitor
|
||||||
try {
|
try {
|
||||||
fillAddLevel('test', level2.difficulty_factor);
|
fillAddLevel("test", level2.difficulty_factor);
|
||||||
getLevelFields(2);
|
getLevelFields(2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe(visNumErr);
|
expect(e.message).toBe(visNumErr);
|
||||||
@ -43,7 +43,7 @@ it('get levels fields works', () => {
|
|||||||
|
|
||||||
// Nan difficulty_factor
|
// Nan difficulty_factor
|
||||||
try {
|
try {
|
||||||
fillAddLevel(level2.visitor_threshold, 'fooasdads');
|
fillAddLevel(level2.visitor_threshold, "fooasdads");
|
||||||
getLevelFields(2);
|
getLevelFields(2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe(diffNumErr);
|
expect(e.message).toBe(diffNumErr);
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Level} from './index';
|
import { Level } from "./index";
|
||||||
import CONST from '../const';
|
import CONST from "../const";
|
||||||
|
|
||||||
import log from '../../../../../logger';
|
import log from "../../../../../logger";
|
||||||
|
|
||||||
/** Fetches level from DOM using the ID passesd and validates */
|
/** Fetches level from DOM using the ID passesd and validates */
|
||||||
const getLevelFields = (id: number) => {
|
const getLevelFields = (id: number): Level => {
|
||||||
log.debug(`[getLevelFields]: id: ${id}`);
|
log.debug(`[getLevelFields]: id: ${id}`);
|
||||||
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
|
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
|
||||||
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
|
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
|
||||||
@ -35,11 +35,11 @@ const getLevelFields = (id: number) => {
|
|||||||
const difficulty_factor = parseInt(difficultyElement.value);
|
const difficulty_factor = parseInt(difficultyElement.value);
|
||||||
|
|
||||||
if (Number.isNaN(visitor_threshold)) {
|
if (Number.isNaN(visitor_threshold)) {
|
||||||
throw new Error('visitor can contain nubers only');
|
throw new Error("visitor can contain nubers only");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Number.isNaN(difficulty_factor)) {
|
if (Number.isNaN(difficulty_factor)) {
|
||||||
throw new Error('difficulty can contain nubers only');
|
throw new Error("difficulty can contain nubers only");
|
||||||
}
|
}
|
||||||
|
|
||||||
const level: Level = {
|
const level: Level = {
|
||||||
@ -48,7 +48,7 @@ const getLevelFields = (id: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
log.debug(
|
log.debug(
|
||||||
`[getLevelFields.ts] visitor: ${visitor_threshold} difficulty: ${difficulty_factor}`,
|
`[getLevelFields.ts] visitor: ${visitor_threshold} difficulty: ${difficulty_factor}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from './getNumLevels';
|
import getNumLevels from "./getNumLevels";
|
||||||
import {getAddForm, addLevel} from '../setupTests';
|
import {getAddForm, addLevel} from "../setupTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
it('get num levels works', () => {
|
it("get num levels works", () => {
|
||||||
expect(getNumLevels()).toBe(1);
|
expect(getNumLevels()).toBe(1);
|
||||||
addLevel(2, 4);
|
addLevel(2, 4);
|
||||||
expect(getNumLevels()).toBe(2);
|
expect(getNumLevels()).toBe(2);
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import CONST from '../const';
|
import CONST from "../const";
|
||||||
|
|
||||||
import log from '../../../../../logger';
|
import log from "../../../../../logger";
|
||||||
|
|
||||||
/** returns number of level input fields currently in DOM */
|
/** returns number of level input fields currently in DOM */
|
||||||
const getNumLevels = () => {
|
const getNumLevels = (): number => {
|
||||||
let numLevels = 0;
|
let numLevels = 0;
|
||||||
document
|
document
|
||||||
.querySelectorAll(`.${CONST.LEVEL_CONTAINER_CLASS}`)
|
.querySelectorAll(`.${CONST.LEVEL_CONTAINER_CLASS}`)
|
||||||
.forEach(_ => numLevels++);
|
.forEach(() => numLevels++);
|
||||||
log.debug(`[getNumLevels]: numLevels: ${numLevels}`);
|
log.debug(`[getNumLevels]: numLevels: ${numLevels}`);
|
||||||
return numLevels;
|
return numLevels;
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import log from '../../../../../logger';
|
import log from "../../../../../logger";
|
||||||
|
|
||||||
/** Datatype represenging an mCaptcha level */
|
/** Datatype represenging an mCaptcha level */
|
||||||
export type Level = {
|
export type Level = {
|
||||||
@ -95,7 +95,7 @@ export const LEVELS = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
levels.levels = tmpLevel.levels;
|
levels.levels = tmpLevel.levels;
|
||||||
log.debug(`post update:`);
|
log.debug("post update:");
|
||||||
LEVELS.print();
|
LEVELS.print();
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -133,7 +133,7 @@ export const LEVELS = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
levels.levels = tmpLevel.levels;
|
levels.levels = tmpLevel.levels;
|
||||||
log.debug('Post remove:');
|
log.debug("Post remove:");
|
||||||
LEVELS.print();
|
LEVELS.print();
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LEVELS, Level} from './index';
|
import {LEVELS, Level} from "./index";
|
||||||
import {level1, level1visErr, level1diffErr, level2} from '../setupTests';
|
import {level1, level1visErr, level1diffErr, level2} from "../setupTests";
|
||||||
|
|
||||||
const visitorErr = 'visitor count should be greater than previous levels';
|
const visitorErr = "visitor count should be greater than previous levels";
|
||||||
const difficultyErr = 'difficulty should be greater than previous levels';
|
const difficultyErr = "difficulty should be greater than previous levels";
|
||||||
|
|
||||||
const zeroVisError = 'visitors must be greater than zero';
|
const zeroVisError = "visitors must be greater than zero";
|
||||||
const zeroDiffError = 'difficulty must be greater than zero';
|
const zeroDiffError = "difficulty must be greater than zero";
|
||||||
|
|
||||||
const zeroVis: Level = {
|
const zeroVis: Level = {
|
||||||
difficulty_factor: 10,
|
difficulty_factor: 10,
|
||||||
@ -34,7 +34,7 @@ const zeroDiff: Level = {
|
|||||||
visitor_threshold: 10,
|
visitor_threshold: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('LEVELS works', () => {
|
it("LEVELS works", () => {
|
||||||
// add level
|
// add level
|
||||||
LEVELS.add(level1);
|
LEVELS.add(level1);
|
||||||
expect(LEVELS.getLevels()).toEqual([level1]);
|
expect(LEVELS.getLevels()).toEqual([level1]);
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import CONST from '../const';
|
import CONST from "../const";
|
||||||
import getLevelFields from './getLevelFields';
|
import getLevelFields from "./getLevelFields";
|
||||||
import {LEVELS} from './index';
|
import { LEVELS } from "./index";
|
||||||
|
|
||||||
import createError from '../../../../../components/error';
|
import createError from "../../../../../components/error";
|
||||||
|
|
||||||
/** on-change event handler to update level */
|
/** on-change event handler to update level */
|
||||||
const updateLevel = (e: Event) => {
|
const updateLevel = (e: Event): void => {
|
||||||
const target = <HTMLInputElement>e.target;
|
const target = <HTMLInputElement>e.target;
|
||||||
|
|
||||||
const id = target.id;
|
const id = target.id;
|
||||||
@ -36,7 +36,7 @@ const updateLevel = (e: Event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Number.isNaN(level)) {
|
if (Number.isNaN(level)) {
|
||||||
console.error(`[updateLevel.ts] level # computed is not correct, got NaN`);
|
console.error("[updateLevel.ts] level # computed is not correct, got NaN");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -48,7 +48,7 @@ const updateLevel = (e: Event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** registers on-change event handlers to update levels */
|
/** registers on-change event handlers to update levels */
|
||||||
export const register = (id: number) => {
|
export const register = (id: number): void => {
|
||||||
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
|
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
|
||||||
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
|
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
|
||||||
|
|
||||||
@ -57,6 +57,6 @@ export const register = (id: number) => {
|
|||||||
document.getElementById(difficultyID)
|
document.getElementById(difficultyID)
|
||||||
);
|
);
|
||||||
|
|
||||||
visitorElement.addEventListener('input', updateLevel, false);
|
visitorElement.addEventListener("input", updateLevel, false);
|
||||||
difficultyElement.addEventListener('input', updateLevel, false);
|
difficultyElement.addEventListener("input", updateLevel, false);
|
||||||
};
|
};
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import validateLevel from './validateLevel';
|
import validateLevel from "./validateLevel";
|
||||||
import {getAddForm, level1, fillAddLevel} from '../setupTests';
|
import {getAddForm, level1, fillAddLevel} from "../setupTests";
|
||||||
import setup from '../../../../../components/error/setUpTests';
|
import setup from "../../../../../components/error/setUpTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
document.body.appendChild(setup());
|
document.body.appendChild(setup());
|
||||||
|
|
||||||
it('validate levels fields works', () => {
|
it("validate levels fields works", () => {
|
||||||
// null error
|
// null error
|
||||||
expect(validateLevel(1)).toEqual(false);
|
expect(validateLevel(1)).toEqual(false);
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LEVELS} from './index';
|
import {LEVELS} from "./index";
|
||||||
import getLevelFields from './getLevelFields';
|
import getLevelFields from "./getLevelFields";
|
||||||
import createError from '../../../../../components/error/';
|
import createError from "../../../../../components/error/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches level from DOM using the ID passesd and validates
|
* Fetches level from DOM using the ID passesd and validates
|
||||||
* its contents
|
* its contents
|
||||||
* */
|
* */
|
||||||
const validateLevel = (id: number) => {
|
const validateLevel = (id: number): boolean => {
|
||||||
try {
|
try {
|
||||||
const level = getLevelFields(id);
|
const level = getLevelFields(id);
|
||||||
LEVELS.add(level);
|
LEVELS.add(level);
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {LEVELS} from '../levels/index';
|
import { LEVELS } from "../levels/index";
|
||||||
import updateLevelNumbersOnDOM from './updateDom';
|
import updateLevelNumbersOnDOM from "./updateDom";
|
||||||
import CONST from '../const';
|
import CONST from "../const";
|
||||||
|
|
||||||
import log from '../../../../../logger';
|
import log from "../../../../../logger";
|
||||||
|
|
||||||
const REMOVE_LEVEL_BUTTON = 'sitekey-form__level-remove-level-button';
|
const REMOVE_LEVEL_BUTTON = "sitekey-form__level-remove-level-button";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets executed when 'Remove' Button is clicked to remove levels
|
* Gets executed when 'Remove' Button is clicked to remove levels
|
||||||
@ -31,12 +31,12 @@ const removeLevel = (e: Event) => {
|
|||||||
const FIELDSET = <HTMLElement>PARENT.parentElement;
|
const FIELDSET = <HTMLElement>PARENT.parentElement;
|
||||||
|
|
||||||
const levelNum = parseInt(
|
const levelNum = parseInt(
|
||||||
eventTarget.id.slice(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL.length),
|
eventTarget.id.slice(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL.length)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Number.isNaN(levelNum)) {
|
if (Number.isNaN(levelNum)) {
|
||||||
const msg =
|
const msg =
|
||||||
'[removeLevelButton.ts] error in parsing level number from remove button ID';
|
"[removeLevelButton.ts] error in parsing level number from remove button ID";
|
||||||
//log.error(msg);
|
//log.error(msg);
|
||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
}
|
}
|
||||||
@ -47,19 +47,19 @@ const removeLevel = (e: Event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** adds onclick event listener */
|
/** adds onclick event listener */
|
||||||
export const addRemoveLevelButtonEventListener = (level: number) => {
|
export const addRemoveLevelButtonEventListener = (level: number): void => {
|
||||||
const removeButton = document.getElementById(
|
const removeButton = document.getElementById(
|
||||||
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`,
|
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`
|
||||||
);
|
);
|
||||||
|
|
||||||
removeButton.addEventListener('click', removeLevel);
|
removeButton.addEventListener("click", removeLevel);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** adds onclick event listener to all remove buttons */
|
/** adds onclick event listener to all remove buttons */
|
||||||
export const addRemoveLevelButtonEventListenerAll = () => {
|
export const addRemoveLevelButtonEventListenerAll = (): void => {
|
||||||
const removeButtons = document.querySelectorAll(`.${REMOVE_LEVEL_BUTTON}`);
|
const removeButtons = document.querySelectorAll(`.${REMOVE_LEVEL_BUTTON}`);
|
||||||
removeButtons.forEach(button =>
|
removeButtons.forEach((button) =>
|
||||||
button.addEventListener('click', removeLevel),
|
button.addEventListener("click", removeLevel)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,20 +67,20 @@ export const addRemoveLevelButtonEventListenerAll = () => {
|
|||||||
* Generate Remove button HTML. On-click handler should be added
|
* Generate Remove button HTML. On-click handler should be added
|
||||||
* seprately
|
* seprately
|
||||||
*/
|
*/
|
||||||
export const getRemoveButtonHTML = (level: number) => {
|
export const getRemoveButtonHTML = (level: number): HTMLLabelElement => {
|
||||||
log.log(`[generating HTML getHtml]level: ${level}`);
|
log.log(`[generating HTML getHtml]level: ${level}`);
|
||||||
|
|
||||||
const btn = document.createElement('input');
|
const btn = document.createElement("input");
|
||||||
btn.className = CONST.REMOVE_LEVEL_BUTTON_CLASS;
|
btn.className = CONST.REMOVE_LEVEL_BUTTON_CLASS;
|
||||||
btn.type = 'button';
|
btn.type = "button";
|
||||||
const id = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`;
|
const id = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`;
|
||||||
btn.name = id;
|
btn.name = id;
|
||||||
btn.id = id;
|
btn.id = id;
|
||||||
btn.value = 'x';
|
btn.value = "x";
|
||||||
|
|
||||||
const removeLabel = document.createElement('label');
|
const removeLabel = document.createElement("label");
|
||||||
removeLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
|
removeLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
|
||||||
const removeLabelText = document.createTextNode('RemoveLevel');
|
const removeLabelText = document.createTextNode("RemoveLevel");
|
||||||
removeLabel.appendChild(removeLabelText);
|
removeLabel.appendChild(removeLabelText);
|
||||||
removeLabel.appendChild(btn);
|
removeLabel.appendChild(btn);
|
||||||
removeLabel.htmlFor = id;
|
removeLabel.htmlFor = id;
|
||||||
|
@ -15,17 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from '../levels/getNumLevels';
|
import getNumLevels from "../levels/getNumLevels";
|
||||||
import {
|
import { getAddForm, addLevel } from "../setupTests";
|
||||||
getAddForm,
|
import CONST from "../const";
|
||||||
getRemoveButtonHTMLForm,
|
|
||||||
trim,
|
|
||||||
addLevel,
|
|
||||||
} from '../setupTests';
|
|
||||||
import CONST from '../const';
|
|
||||||
|
|
||||||
import log from '../../../../../logger';
|
import log from "../../../../../logger";
|
||||||
import {MODE} from '../../../../../logger';
|
import { MODE } from "../../../../../logger";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
@ -46,13 +41,13 @@ const setUp = () => {
|
|||||||
|
|
||||||
log.setMode(MODE.none);
|
log.setMode(MODE.none);
|
||||||
|
|
||||||
it('removeLevelButton works', () => {
|
it("removeLevelButton works", () => {
|
||||||
setUp();
|
setUp();
|
||||||
|
|
||||||
for (let i = 1; i < 4; i++) {
|
for (let i = 1; i < 4; i++) {
|
||||||
const l1 = <HTMLButtonElement>(
|
const l1 = <HTMLButtonElement>(
|
||||||
document.getElementById(
|
document.getElementById(
|
||||||
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${1}`,
|
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${1}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -14,25 +14,25 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import getNumLevels from '../../levels/getNumLevels';
|
import getNumLevels from "../../levels/getNumLevels";
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
|
|
||||||
import updateLabels from './updateLabel';
|
import updateLabels from "./updateLabel";
|
||||||
import updateInputs from './updateInputs';
|
import updateInputs from "./updateInputs";
|
||||||
import updateRemoveButton from './updateRemoveButton';
|
import updateRemoveButton from "./updateRemoveButton";
|
||||||
import updateLevelGroup from './updateLevelGroup';
|
import updateLevelGroup from "./updateLevelGroup";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update level number on fieldset legends and their ids too
|
* update level number on fieldset legends and their ids too
|
||||||
* @param {number} id - level number that was ordered to remove.
|
* @param {number} id - level number that was ordered to remove.
|
||||||
* All updates are made relative to id
|
* All updates are made relative to id
|
||||||
* */
|
* */
|
||||||
const updateLevelNumbersOnDOM = (id: number) => {
|
const updateLevelNumbersOnDOM = (id: number): void => {
|
||||||
const numLevels = getNumLevels();
|
const numLevels = getNumLevels();
|
||||||
if (id == numLevels) {
|
if (id == numLevels) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Can't remove the very fist element, it has to be first added to DOM",
|
"Can't remove the very fist element, it has to be first added to DOM"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ const updateLevelNumbersOnDOM = (id: number) => {
|
|||||||
const newLevel = i - 1;
|
const newLevel = i - 1;
|
||||||
|
|
||||||
const levelGroup = document.querySelector(
|
const levelGroup = document.querySelector(
|
||||||
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${i}`,
|
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${i}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (levelGroup === null) {
|
if (levelGroup === null) {
|
||||||
@ -53,9 +53,9 @@ const updateLevelNumbersOnDOM = (id: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rename legend
|
// rename legend
|
||||||
const legend = levelGroup.getElementsByTagName('legend')[0];
|
const legend = levelGroup.getElementsByTagName("legend")[0];
|
||||||
const legendText = document.createTextNode(`Level ${newLevel}`);
|
const legendText = document.createTextNode(`Level ${newLevel}`);
|
||||||
const newLegend = document.createElement('legend');
|
const newLegend = document.createElement("legend");
|
||||||
newLegend.className = legend.className;
|
newLegend.className = legend.className;
|
||||||
newLegend.appendChild(legendText);
|
newLegend.appendChild(legendText);
|
||||||
legend.replaceWith(newLegend);
|
legend.replaceWith(newLegend);
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from '../../levels/getNumLevels';
|
import getNumLevels from "../../levels/getNumLevels";
|
||||||
import {getAddForm, addLevel} from '../../setupTests';
|
import { getAddForm, addLevel } from "../../setupTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
export const setupAddlevels = () => {
|
export const setupAddlevels = (): void => {
|
||||||
expect(getNumLevels()).toBe(1);
|
expect(getNumLevels()).toBe(1);
|
||||||
// add a level
|
// add a level
|
||||||
addLevel(2, 2);
|
addLevel(2, 2);
|
||||||
|
@ -15,20 +15,20 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getAddForm, trim} from '../../setupTests';
|
import {getAddForm, trim} from "../../setupTests";
|
||||||
import updateInputs from './updateInputs';
|
import updateInputs from "./updateInputs";
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
|
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
import {MODE} from '../../../../../../logger';
|
import {MODE} from "../../../../../../logger";
|
||||||
|
|
||||||
import {setupAddlevels} from './setupTests';
|
import {setupAddlevels} from "./setupTests";
|
||||||
|
|
||||||
document.body.innerHTML = getAddForm();
|
document.body.innerHTML = getAddForm();
|
||||||
|
|
||||||
log.setMode(MODE.none);
|
log.setMode(MODE.none);
|
||||||
|
|
||||||
it('updateInputs works', () => {
|
it("updateInputs works", () => {
|
||||||
setupAddlevels();
|
setupAddlevels();
|
||||||
// removing level 2
|
// removing level 2
|
||||||
const level = 2;
|
const level = 2;
|
||||||
@ -58,7 +58,7 @@ it('updateInputs works', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/** get initial form to test remove button functionality */
|
/** get initial form to test remove button functionality */
|
||||||
export const update = () => {
|
export const update = (): string => {
|
||||||
return `
|
return `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<h1 class="form__title">
|
<h1 class="form__title">
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
|
|
||||||
/** update input IDs with new level */
|
/** update input IDs with new level */
|
||||||
const updateInput = (levelGroup: Element, newLevel: number) => {
|
const updateInput = (levelGroup: Element, newLevel: number): void => {
|
||||||
const inputs = <NodeListOf<HTMLInputElement>>(
|
const inputs = <NodeListOf<HTMLInputElement>>(
|
||||||
levelGroup.querySelectorAll(`.${CONST.LEVEL_INPUT_CLASS}`)
|
levelGroup.querySelectorAll(`.${CONST.LEVEL_INPUT_CLASS}`)
|
||||||
);
|
);
|
||||||
@ -26,17 +26,17 @@ const updateInput = (levelGroup: Element, newLevel: number) => {
|
|||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
if (input.id.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
if (input.id.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
||||||
log.log(`${input.id}`);
|
log.log(`${input.id}`);
|
||||||
log.log('changing visitor_threshold input');
|
log.log("changing visitor_threshold input");
|
||||||
const id = `${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`;
|
const id = `${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`;
|
||||||
input.id = id;
|
input.id = id;
|
||||||
input.name = id;
|
input.name = id;
|
||||||
} else if (input.id.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
|
} else if (input.id.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
|
||||||
log.log('changing difficulty input');
|
log.log("changing difficulty input");
|
||||||
const id = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`;
|
const id = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`;
|
||||||
input.id = id;
|
input.id = id;
|
||||||
input.name = id;
|
input.name = id;
|
||||||
} else {
|
} else {
|
||||||
if (input.id != 'add') {
|
if (input.id != "add") {
|
||||||
throw new Error(`Did you add an extra input to DOM? ${input.id} ${input.className} ${input.name}`);
|
throw new Error(`Did you add an extra input to DOM? ${input.id} ${input.className} ${input.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from '../../levels/getNumLevels';
|
import { trim } from "../../setupTests";
|
||||||
import {getAddForm, trim} from '../../setupTests';
|
import updateLabels from "./updateLabel";
|
||||||
import updateLabels from './updateLabel';
|
import CONST from "../../const";
|
||||||
import CONST from '../../const';
|
|
||||||
|
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
import {MODE} from '../../../../../../logger';
|
import { MODE } from "../../../../../../logger";
|
||||||
|
|
||||||
import {setupAddlevels} from './setupTests';
|
|
||||||
|
|
||||||
/** get initial form to test remove button functionality */
|
/** get initial form to test remove button functionality */
|
||||||
export const labelLevel = (level: number) => {
|
export const labelLevel = (level: number): string => {
|
||||||
return `
|
return `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<fieldset class="sitekey__level-container" id="level-group-2">
|
<fieldset class="sitekey__level-container" id="level-group-2">
|
||||||
@ -85,11 +82,11 @@ document.body.innerHTML = labelLevel(2);
|
|||||||
|
|
||||||
log.setMode(MODE.none);
|
log.setMode(MODE.none);
|
||||||
|
|
||||||
it('addLevelButton works', () => {
|
it("addLevelButton works", () => {
|
||||||
// removing level 2
|
// removing level 2
|
||||||
const level = 2;
|
const level = 2;
|
||||||
const levelGroup = document.querySelector(
|
const levelGroup = document.querySelector(
|
||||||
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`,
|
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const newLevel = 20;
|
const newLevel = 20;
|
||||||
@ -100,22 +97,22 @@ it('addLevelButton works', () => {
|
|||||||
levelGroup.querySelectorAll(`.${CONST.LABEL_CLASS}`)
|
levelGroup.querySelectorAll(`.${CONST.LABEL_CLASS}`)
|
||||||
);
|
);
|
||||||
log.log(labels);
|
log.log(labels);
|
||||||
labels.forEach(label => {
|
labels.forEach((label) => {
|
||||||
log.log(`${label.htmlFor}`);
|
log.log(`${label.htmlFor}`);
|
||||||
if (label.htmlFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
if (label.htmlFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
||||||
expect(label.htmlFor).toBe(`${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`);
|
expect(label.htmlFor).toBe(`${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`);
|
||||||
} else if (label.htmlFor.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
|
} else if (label.htmlFor.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
|
||||||
expect(label.htmlFor).toBe(
|
expect(label.htmlFor).toBe(
|
||||||
`${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`,
|
`${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
label.htmlFor.includes(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL)
|
label.htmlFor.includes(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL)
|
||||||
) {
|
) {
|
||||||
expect(label.htmlFor).toBe(
|
expect(label.htmlFor).toBe(
|
||||||
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`,
|
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Did you add an extra label to DOM?');
|
throw new Error("Did you add an extra label to DOM?");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,17 +14,17 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
|
|
||||||
/** update level lables to match new level */
|
/** update level lables to match new level */
|
||||||
const updateLabels = (levelGroup: Element, newLevel: number) => {
|
const updateLabels = (levelGroup: Element, newLevel: number): void => {
|
||||||
// rename labels
|
// rename labels
|
||||||
const labels = <NodeListOf<HTMLLabelElement>>(
|
const labels = <NodeListOf<HTMLLabelElement>>(
|
||||||
levelGroup.querySelectorAll(`label`)
|
levelGroup.querySelectorAll("label")
|
||||||
);
|
);
|
||||||
log.log(labels);
|
log.log(labels);
|
||||||
labels.forEach(label => {
|
labels.forEach((label) => {
|
||||||
log.log(`${label.htmlFor}`);
|
log.log(`${label.htmlFor}`);
|
||||||
const currentFor = label.htmlFor;
|
const currentFor = label.htmlFor;
|
||||||
if (currentFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
if (currentFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
|
||||||
@ -36,9 +36,9 @@ const updateLabels = (levelGroup: Element, newLevel: number) => {
|
|||||||
) {
|
) {
|
||||||
label.htmlFor = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`;
|
label.htmlFor = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`;
|
||||||
} else {
|
} else {
|
||||||
if (currentFor != 'add') {
|
if (currentFor != "add") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Did you add an extra label to DOM? Found label with for: ${currentFor}`,
|
`Did you add an extra label to DOM? Found label with for: ${currentFor}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from '../../levels/getNumLevels';
|
import { trim} from "../../setupTests";
|
||||||
import {getAddForm, trim} from '../../setupTests';
|
import updateLevelGroup from "./updateLevelGroup";
|
||||||
import updateLevelGroup from './updateLevelGroup';
|
import CONST from "../../const";
|
||||||
import CONST from '../../const';
|
|
||||||
|
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
import {MODE} from '../../../../../../logger';
|
import {MODE} from "../../../../../../logger";
|
||||||
|
|
||||||
import {setupAddlevels} from './setupTests';
|
|
||||||
|
|
||||||
/** get initial form to test remove button functionality */
|
/** get initial form to test remove button functionality */
|
||||||
export const labelLevel = (level: number) => {
|
export const labelLevel = (level: number): string => {
|
||||||
return `
|
return `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<fieldset class="sitekey__level-container" id="level-group-${level}">
|
<fieldset class="sitekey__level-container" id="level-group-${level}">
|
||||||
@ -85,7 +83,7 @@ document.body.innerHTML = labelLevel(2);
|
|||||||
|
|
||||||
log.setMode(MODE.none);
|
log.setMode(MODE.none);
|
||||||
|
|
||||||
it('update levelGroup works', () => {
|
it("update levelGroup works", () => {
|
||||||
// removing level 2
|
// removing level 2
|
||||||
const level = 2;
|
const level = 2;
|
||||||
const levelGroup = document.querySelector(
|
const levelGroup = document.querySelector(
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
|
|
||||||
/** update level grup to match new level */
|
/** update level grup to match new level */
|
||||||
const updateLevelGroup = (levelGroup: Element, newLevel: number) =>
|
const updateLevelGroup = (levelGroup: Element, newLevel: number): string =>
|
||||||
(levelGroup.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${newLevel}`);
|
(levelGroup.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${newLevel}`);
|
||||||
|
|
||||||
export default updateLevelGroup;
|
export default updateLevelGroup;
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {trim} from '../../setupTests';
|
import {trim} from "../../setupTests";
|
||||||
import updateRemoveButton from './updateRemoveButton';
|
import updateRemoveButton from "./updateRemoveButton";
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
|
|
||||||
import log from '../../../../../../logger';
|
import log from "../../../../../../logger";
|
||||||
import {MODE} from '../../../../../../logger';
|
import {MODE} from "../../../../../../logger";
|
||||||
|
|
||||||
/** get initial form to test remove button functionality */
|
/** get initial form to test remove button functionality */
|
||||||
export const labelLevel = (level: number) => {
|
export const labelLevel = (level: number): string => {
|
||||||
return `
|
return `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<fieldset class="sitekey__level-container" id="level-group-">
|
<fieldset class="sitekey__level-container" id="level-group-">
|
||||||
@ -83,7 +83,7 @@ document.body.innerHTML = labelLevel(level);
|
|||||||
|
|
||||||
log.setMode(MODE.none);
|
log.setMode(MODE.none);
|
||||||
|
|
||||||
it('update remove button works', () => {
|
it("update remove button works", () => {
|
||||||
// removing level 2
|
// removing level 2
|
||||||
|
|
||||||
const levelGroup = document.getElementById(
|
const levelGroup = document.getElementById(
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import CONST from '../../const';
|
import CONST from "../../const";
|
||||||
|
|
||||||
/** update remove level button's ID */
|
/** update remove level button's ID */
|
||||||
const updateRemoveButton = (levelGroup: Element, newLevel: number) => {
|
const updateRemoveButton = (levelGroup: Element, newLevel: number): void => {
|
||||||
// rename button
|
// rename button
|
||||||
const button = <HTMLInputElement>(
|
const button = <HTMLInputElement>(
|
||||||
levelGroup.querySelector(`.${CONST.REMOVE_LEVEL_BUTTON_CLASS}`)
|
levelGroup.querySelector(`.${CONST.REMOVE_LEVEL_BUTTON_CLASS}`)
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import getNumLevels from './levels/getNumLevels';
|
import getNumLevels from "./levels/getNumLevels";
|
||||||
import {Level} from './levels/index';
|
import { Level } from "./levels/index";
|
||||||
import CONST from './const';
|
import CONST from "./const";
|
||||||
import addLevelButtonAddEventListener from './addLevelButton';
|
import addLevelButtonAddEventListener from "./addLevelButton";
|
||||||
|
|
||||||
/** get rid of all whitespaces, useful when comparing DOM states */
|
/** get rid of all whitespaces, useful when comparing DOM states */
|
||||||
export const trim = (s: string) => s.replace(/\s/g, '');
|
export const trim = (s: string): string => s.replace(/\s/g, "");
|
||||||
|
|
||||||
export const level1: Level = {
|
export const level1: Level = {
|
||||||
difficulty_factor: 200,
|
difficulty_factor: 200,
|
||||||
@ -43,7 +43,7 @@ export const level2: Level = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** add level to DOM by filling add level form and clicking "Add" button */
|
/** add level to DOM by filling add level form and clicking "Add" button */
|
||||||
export const addLevel = (visitor: number, diff: number) => {
|
export const addLevel = (visitor: number, diff: number): void => {
|
||||||
fillAddLevel(visitor, diff);
|
fillAddLevel(visitor, diff);
|
||||||
const addLevelButton = <HTMLElement>(
|
const addLevelButton = <HTMLElement>(
|
||||||
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
|
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
|
||||||
@ -54,8 +54,8 @@ export const addLevel = (visitor: number, diff: number) => {
|
|||||||
/** Fill add level form without clicking add button */
|
/** Fill add level form without clicking add button */
|
||||||
export const fillAddLevel = (
|
export const fillAddLevel = (
|
||||||
visitor: number | string,
|
visitor: number | string,
|
||||||
diff: number | string,
|
diff: number | string
|
||||||
) => {
|
): void => {
|
||||||
addLevelButtonAddEventListener();
|
addLevelButtonAddEventListener();
|
||||||
|
|
||||||
const level = getNumLevels();
|
const level = getNumLevels();
|
||||||
@ -71,7 +71,11 @@ export const fillAddLevel = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Fill add level form without clicking add button */
|
/** Fill add level form without clicking add button */
|
||||||
export const editLevel = (level: number, visitor?: number, diff?: number) => {
|
export const editLevel = (
|
||||||
|
level: number,
|
||||||
|
visitor?: number,
|
||||||
|
diff?: number
|
||||||
|
): void => {
|
||||||
if (visitor !== undefined) {
|
if (visitor !== undefined) {
|
||||||
const visitorField = <HTMLInputElement>(
|
const visitorField = <HTMLInputElement>(
|
||||||
document.getElementById(`${CONST.VISITOR_WITHOUT_LEVEL}${level}`)
|
document.getElementById(`${CONST.VISITOR_WITHOUT_LEVEL}${level}`)
|
||||||
@ -88,18 +92,18 @@ export const editLevel = (level: number, visitor?: number, diff?: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Fill description in add level form */
|
/** Fill description in add level form */
|
||||||
export const fillDescription = (description: string) => {
|
export const fillDescription = (description: string): void => {
|
||||||
const inputElement = <HTMLInputElement>document.getElementById('description');
|
const inputElement = <HTMLInputElement>document.getElementById("description");
|
||||||
inputElement.value = description;
|
inputElement.value = description;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Fill duration in add level form */
|
/** Fill duration in add level form */
|
||||||
export const fillDuration = (duration: number | string) => {
|
export const fillDuration = (duration: number | string): void => {
|
||||||
const inputElement = <HTMLInputElement>document.getElementById('duration');
|
const inputElement = <HTMLInputElement>document.getElementById("duration");
|
||||||
inputElement.value = duration.toString();
|
inputElement.value = duration.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAddForm = () => `
|
export const getAddForm = (): string => `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<h1 class="form__title">
|
<h1 class="form__title">
|
||||||
Add Sitekey
|
Add Sitekey
|
||||||
@ -171,7 +175,7 @@ export const getAddForm = () => `
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
/** get initial form to test remove button functionality */
|
/** get initial form to test remove button functionality */
|
||||||
export const getRemoveButtonHTMLForm = () => {
|
export const getRemoveButtonHTMLForm = (): string => {
|
||||||
return `
|
return `
|
||||||
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
|
||||||
<h1 class="form__title">
|
<h1 class="form__title">
|
||||||
|
@ -15,16 +15,16 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getPassword} from '../../../auth/login/ts/';
|
import { getPassword } from "../../../auth/login/ts/";
|
||||||
import FORM from '../../../auth/sudo/';
|
import FORM from "../../../auth/sudo/";
|
||||||
import additionalData from '../../../components/additional-data';
|
import additionalData from "../../../components/additional-data";
|
||||||
import registerShowPassword from '../../../components/showPassword';
|
import registerShowPassword from "../../../components/showPassword";
|
||||||
|
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error';
|
import createError from "../../../components/error";
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
const submit = async (e: Event) => {
|
const submit = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -47,7 +47,7 @@ const submit = async (e: Event) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
FORM.get().addEventListener('submit', submit, true);
|
FORM.get().addEventListener("submit", submit, true);
|
||||||
registerShowPassword();
|
registerShowPassword();
|
||||||
};
|
};
|
||||||
|
@ -15,17 +15,17 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getNumLevels from '../add/ts/levels/getNumLevels';
|
import getNumLevels from "../add/ts/levels/getNumLevels";
|
||||||
import {addLevel} from '../add/ts/setupTests';
|
import {addLevel} from "../add/ts/setupTests";
|
||||||
import setup from '../../../components/error/setUpTests';
|
import setup from "../../../components/error/setUpTests";
|
||||||
import * as SETUP from './setupTest';
|
import * as SETUP from "./setupTest";
|
||||||
|
|
||||||
document.body.innerHTML = SETUP.EDIT_FORM;
|
document.body.innerHTML = SETUP.EDIT_FORM;
|
||||||
document.body.appendChild(setup());
|
document.body.appendChild(setup());
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
it('edit sitekey works', () => {
|
it("edit sitekey works", () => {
|
||||||
expect(getNumLevels()).toBe(2);
|
expect(getNumLevels()).toBe(2);
|
||||||
// add a level
|
// add a level
|
||||||
addLevel(5, 6);
|
addLevel(5, 6);
|
||||||
|
@ -14,31 +14,31 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import * as Add from '../add/ts/form/';
|
import * as Add from "../add/ts/form/";
|
||||||
import addLevelButtonAddEventListener from '../add/ts/addLevelButton';
|
import addLevelButtonAddEventListener from "../add/ts/addLevelButton";
|
||||||
import {addRemoveLevelButtonEventListenerAll} from '../add/ts/removeLevelButton';
|
import { addRemoveLevelButtonEventListenerAll } from "../add/ts/removeLevelButton";
|
||||||
import getNumLevels from '../add/ts/levels/getNumLevels';
|
import getNumLevels from "../add/ts/levels/getNumLevels";
|
||||||
import validateLevel from '../add/ts/levels/validateLevel';
|
import validateLevel from "../add/ts/levels/validateLevel";
|
||||||
import * as UpdateLevel from '../add/ts/levels/updateLevel';
|
import * as UpdateLevel from "../add/ts/levels/updateLevel";
|
||||||
import validateDescription from '../add/ts/form/validateDescription';
|
import validateDescription from "../add/ts/form/validateDescription";
|
||||||
import validateDuration from '../add/ts/form/validateDuration';
|
import validateDuration from "../add/ts/form/validateDuration";
|
||||||
import {LEVELS} from '../add/ts/levels';
|
import { LEVELS } from "../add/ts/levels";
|
||||||
|
|
||||||
import getFormUrl from '../../../utils/getFormUrl';
|
import getFormUrl from "../../../utils/getFormUrl";
|
||||||
import genJsonPayload from '../../../utils/genJsonPayload';
|
import genJsonPayload from "../../../utils/genJsonPayload";
|
||||||
import createError from '../../../components/error';
|
import createError from "../../../components/error";
|
||||||
import LazyElement from '../../../utils/lazyElement';
|
import LazyElement from "../../../utils/lazyElement";
|
||||||
|
|
||||||
import VIEWS from '../../../views/v1/routes';
|
import VIEWS from "../../../views/v1/routes";
|
||||||
|
|
||||||
const BTN_ID = 'sitekey-form__submit';
|
const BTN_ID = "sitekey-form__submit";
|
||||||
const BTN = new LazyElement(BTN_ID);
|
const BTN = new LazyElement(BTN_ID);
|
||||||
|
|
||||||
const submit = async (e: Event) => {
|
const submit = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const description = validateDescription(e);
|
const description = validateDescription(e);
|
||||||
const duration = validateDuration(e);
|
const duration = validateDuration();
|
||||||
|
|
||||||
const formUrl = getFormUrl(Add.FORM);
|
const formUrl = getFormUrl(Add.FORM);
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ const submit = async (e: Event) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const addSubmitEventListener = () => {
|
const addSubmitEventListener = () => {
|
||||||
Add.FORM.addEventListener('submit', submit, true);
|
Add.FORM.addEventListener("submit", submit, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bootstrapLevels = () => {
|
const bootstrapLevels = () => {
|
||||||
@ -78,7 +78,7 @@ const bootstrapLevels = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
addSubmitEventListener();
|
addSubmitEventListener();
|
||||||
addLevelButtonAddEventListener();
|
addLevelButtonAddEventListener();
|
||||||
bootstrapLevels();
|
bootstrapLevels();
|
||||||
|
@ -14,17 +14,17 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import CopyIcon from '../../../../components/clipboard/';
|
import CopyIcon from "../../../../components/clipboard/";
|
||||||
|
|
||||||
const SITEKEY_COPY_ICON = `sitekey__copy-icon`;
|
const SITEKEY_COPY_ICON = "sitekey__copy-icon";
|
||||||
const SITEKEY_COPY_DONE_ICON = `sitekey__copy-done-icon`;
|
const SITEKEY_COPY_DONE_ICON = "sitekey__copy-done-icon";
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => {
|
||||||
const image = document.querySelectorAll(`.${SITEKEY_COPY_ICON}`);
|
const image = document.querySelectorAll(`.${SITEKEY_COPY_ICON}`);
|
||||||
image.forEach((img: HTMLElement) => {
|
image.forEach((img: HTMLElement) => {
|
||||||
if (!img.classList.contains(SITEKEY_COPY_ICON)) {
|
if (!img.classList.contains(SITEKEY_COPY_ICON)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'This method should only be called when sitekey copy button/icon is clicked',
|
"This method should only be called when sitekey copy button/icon is clicked"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const sitekey = img.dataset.sitekey;
|
const sitekey = img.dataset.sitekey;
|
||||||
|
@ -14,4 +14,4 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
export const index = () => {};
|
//export const index = () => {};
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as listSitekeys from '../sitekey/list/ts/';
|
import * as listSitekeys from "../sitekey/list/ts/";
|
||||||
|
|
||||||
export const index = () => {
|
export const index = (): void => listSitekeys.index();
|
||||||
listSitekeys.index();
|
|
||||||
};
|
|
||||||
|
@ -15,29 +15,29 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Router} from './router';
|
import {Router} from "./router";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
result: '',
|
result: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const panelResult = 'hello from panel';
|
const panelResult = "hello from panel";
|
||||||
const panelRoute = '/panel';
|
const panelRoute = "/panel";
|
||||||
const panel = () => (result.result = panelResult);
|
const panel = () => (result.result = panelResult);
|
||||||
|
|
||||||
const settingsRoute = '/sitekey/';
|
const settingsRoute = "/sitekey/";
|
||||||
const settingsResult = 'hello from settings';
|
const settingsResult = "hello from settings";
|
||||||
const settings = () => (result.result = settingsResult);
|
const settings = () => (result.result = settingsResult);
|
||||||
|
|
||||||
const patternRoute = '/sitekey/[A-Z,a-z,0-9,_]+/';
|
const patternRoute = "/sitekey/[A-Z,a-z,0-9,_]+/";
|
||||||
const examplePatternRoute = '/sitekey/alksdjakdjadajkhdjahrjke234/';
|
const examplePatternRoute = "/sitekey/alksdjakdjadajkhdjahrjke234/";
|
||||||
const patterResult = 'hello from pattern route';
|
const patterResult = "hello from pattern route";
|
||||||
const pattern = () => (result.result = patterResult);
|
const pattern = () => (result.result = patterResult);
|
||||||
|
|
||||||
const UriExistsErr = 'URI exists';
|
const UriExistsErr = "URI exists";
|
||||||
const emptyUriErr = 'uri is empty';
|
const emptyUriErr = "uri is empty";
|
||||||
const unregisteredRouteErr = "Route isn't registered";
|
const unregisteredRouteErr = "Route isn't registered";
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
@ -45,23 +45,23 @@ router.register(patternRoute, pattern);
|
|||||||
router.register(panelRoute, panel);
|
router.register(panelRoute, panel);
|
||||||
router.register(settingsRoute, settings);
|
router.register(settingsRoute, settings);
|
||||||
|
|
||||||
it('checks if Router works', () => {
|
it("checks if Router works", () => {
|
||||||
window.history.pushState({}, '', examplePatternRoute);
|
window.history.pushState({}, "", examplePatternRoute);
|
||||||
router.route();
|
router.route();
|
||||||
expect(result.result).toBe(patterResult);
|
expect(result.result).toBe(patterResult);
|
||||||
|
|
||||||
window.history.pushState(
|
window.history.pushState(
|
||||||
{},
|
{},
|
||||||
'',
|
"",
|
||||||
examplePatternRoute.slice(0, examplePatternRoute.length - 1),
|
examplePatternRoute.slice(0, examplePatternRoute.length - 1),
|
||||||
);
|
);
|
||||||
router.route();
|
router.route();
|
||||||
expect(result.result).toBe(patterResult);
|
expect(result.result).toBe(patterResult);
|
||||||
|
|
||||||
window.history.pushState({}, 'Settings', settingsRoute);
|
window.history.pushState({}, "Settings", settingsRoute);
|
||||||
router.route();
|
router.route();
|
||||||
expect(result.result).toBe(settingsResult);
|
expect(result.result).toBe(settingsResult);
|
||||||
window.history.pushState({}, 'Panel', panelRoute);
|
window.history.pushState({}, "Panel", panelRoute);
|
||||||
router.route();
|
router.route();
|
||||||
expect(result.result).toBe(panelResult);
|
expect(result.result).toBe(panelResult);
|
||||||
|
|
||||||
@ -74,14 +74,14 @@ it('checks if Router works', () => {
|
|||||||
|
|
||||||
// empty URI registration
|
// empty URI registration
|
||||||
try {
|
try {
|
||||||
router.register(' ', settings);
|
router.register(" ", settings);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe(emptyUriErr);
|
expect(e.message).toBe(emptyUriErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// routing to unregistered route
|
// routing to unregistered route
|
||||||
try {
|
try {
|
||||||
window.history.pushState({}, `Page Doesn't Exist`, `/page/doesnt/exist`);
|
window.history.pushState({}, "Page Doesn't Exist", "/page/doesnt/exist");
|
||||||
router.route();
|
router.route();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe(unregisteredRouteErr);
|
expect(e.message).toBe(unregisteredRouteErr);
|
||||||
@ -89,7 +89,7 @@ it('checks if Router works', () => {
|
|||||||
|
|
||||||
// routing to unregistered route
|
// routing to unregistered route
|
||||||
try {
|
try {
|
||||||
window.history.pushState({}, `Page Doesn't Exist`, `/sitekey/;asd;lasdj`);
|
window.history.pushState({}, "Page Doesn't Exist", "/sitekey/;asd;lasdj");
|
||||||
router.route();
|
router.route();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe(unregisteredRouteErr);
|
expect(e.message).toBe(unregisteredRouteErr);
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
const normalizeUri = (uri: string) => {
|
const normalizeUri = (uri: string) => {
|
||||||
uri = uri.trim();
|
uri = uri.trim();
|
||||||
if (uri.length == 0) {
|
if (uri.length == 0) {
|
||||||
throw new Error('uri is empty');
|
throw new Error("uri is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
let uriLength = uri.length;
|
const uriLength = uri.length;
|
||||||
if (uri[uriLength - 1] == '/') {
|
if (uri[uriLength - 1] == "/") {
|
||||||
uri = uri.slice(0, uriLength - 1);
|
uri = uri.slice(0, uriLength - 1);
|
||||||
}
|
}
|
||||||
return uri;
|
return uri;
|
||||||
@ -51,14 +51,14 @@ export class Router {
|
|||||||
* @param {function} fn: - function to be registered when window.locatin.path
|
* @param {function} fn: - function to be registered when window.locatin.path
|
||||||
* matches uri
|
* matches uri
|
||||||
* */
|
* */
|
||||||
register(uri: string, fn: () => void) {
|
register(uri: string, fn: () => void): void {
|
||||||
uri = normalizeUri(uri);
|
uri = normalizeUri(uri);
|
||||||
|
|
||||||
let pattern = new RegExp(`^${uri}$`);
|
const pattern = new RegExp(`^${uri}$`);
|
||||||
|
|
||||||
let patterString = pattern.toString();
|
const patterString = pattern.toString();
|
||||||
if (
|
if (
|
||||||
this.routes.find(route => {
|
this.routes.find((route) => {
|
||||||
if (route.pattern.toString() == patterString) {
|
if (route.pattern.toString() == patterString) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -66,7 +66,7 @@ export class Router {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
throw new Error('URI exists');
|
throw new Error("URI exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
const route: routeTuple = {
|
const route: routeTuple = {
|
||||||
@ -80,13 +80,13 @@ export class Router {
|
|||||||
* executes registered function with route
|
* executes registered function with route
|
||||||
* matches window.pathname.location
|
* matches window.pathname.location
|
||||||
* */
|
* */
|
||||||
route() {
|
route(): void {
|
||||||
const path = normalizeUri(window.location.pathname);
|
const path = normalizeUri(window.location.pathname);
|
||||||
|
|
||||||
let fn: undefined | (() => void);
|
let fn: undefined | (() => void);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.routes.find(route => {
|
this.routes.find((route) => {
|
||||||
if (path.match(route.pattern)) {
|
if (path.match(route.pattern)) {
|
||||||
fn = route.fn;
|
fn = route.fn;
|
||||||
return true;
|
return true;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** get login form HTML */
|
/** get login form HTML */
|
||||||
export const getLoginFormHtml = () =>
|
export const getLoginFormHtml = (): string =>
|
||||||
`
|
`
|
||||||
<form method="POST" action="/something" id="form">
|
<form method="POST" action="/something" id="form">
|
||||||
<label class="form__in-group" for="username"
|
<label class="form__in-group" for="username"
|
||||||
@ -51,7 +51,7 @@ export const getLoginFormHtml = () =>
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
/** get registration form HTML */
|
/** get registration form HTML */
|
||||||
export const getRegistrationFormHtml = () => `
|
export const getRegistrationFormHtml = (): string => `
|
||||||
<form method="POST" action="/api/v1/signup" class="form__box" id="form">
|
<form method="POST" action="/api/v1/signup" class="form__box" id="form">
|
||||||
<label class="form__in-group" for="username"
|
<label class="form__in-group" for="username"
|
||||||
>Username
|
>Username
|
||||||
@ -104,7 +104,7 @@ export const getRegistrationFormHtml = () => `
|
|||||||
</form>
|
</form>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const mockAlert = () => {
|
export const mockAlert = (): void => {
|
||||||
delete window.alert;
|
delete window.alert;
|
||||||
|
|
||||||
window.alert = (x: any) => console.log(x);
|
window.alert = (x: any) => console.log(x);
|
||||||
|
@ -15,22 +15,22 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import genJsonPayload from './genJsonPayload';
|
import genJsonPayload from "./genJsonPayload";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
username: 'Jhon',
|
username: "Jhon",
|
||||||
};
|
};
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
};
|
};
|
||||||
|
|
||||||
it('getFromUrl workds', () => {
|
it("getFromUrl workds", () => {
|
||||||
expect(genJsonPayload(payload)).toEqual(value);
|
expect(genJsonPayload(payload)).toEqual(value);
|
||||||
});
|
});
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const genJsonPayload = (payload: any) => {
|
const genJsonPayload = (payload: object): object => {
|
||||||
const value = {
|
const value = {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
};
|
};
|
||||||
|
@ -15,27 +15,27 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import getFormUrl from './getFormUrl';
|
import getFormUrl from "./getFormUrl";
|
||||||
import {getLoginFormHtml} from '../setUpTests';
|
import {getLoginFormHtml} from "../setUpTests";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
const formClassName = 'form__box';
|
const formClassName = "form__box";
|
||||||
const formURL = '/api/v1/signin';
|
const formURL = "/api/v1/signin";
|
||||||
|
|
||||||
const noFormErr = "Can't find form";
|
const noFormErr = "Can't find form";
|
||||||
|
|
||||||
document.body.innerHTML = getLoginFormHtml();
|
document.body.innerHTML = getLoginFormHtml();
|
||||||
|
|
||||||
const form = document.querySelector('form');
|
const form = document.querySelector("form");
|
||||||
form.action = formURL;
|
form.action = formURL;
|
||||||
form.className = formClassName;
|
form.className = formClassName;
|
||||||
|
|
||||||
it('getFromUrl workds', () => {
|
it("getFromUrl workds", () => {
|
||||||
const name = `.${formClassName}`;
|
const name = `.${formClassName}`;
|
||||||
expect(getFormUrl(name)).toContain(formURL);
|
expect(getFormUrl(name)).toContain(formURL);
|
||||||
|
|
||||||
const form = <HTMLFormElement>document.querySelector('form');
|
const form = <HTMLFormElement>document.querySelector("form");
|
||||||
expect(getFormUrl(form)).toContain(formURL);
|
expect(getFormUrl(form)).toContain(formURL);
|
||||||
|
|
||||||
expect(getFormUrl()).toContain(formURL);
|
expect(getFormUrl()).toContain(formURL);
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
* So when using class-names, pass in ".whatever-classname"
|
* So when using class-names, pass in ".whatever-classname"
|
||||||
* and for ID, "#id".
|
* and for ID, "#id".
|
||||||
* */
|
* */
|
||||||
const getFormUrl = (querySelector?: string | HTMLFormElement) => {
|
const getFormUrl = (querySelector?: string | HTMLFormElement): string => {
|
||||||
let form;
|
let form;
|
||||||
if (querySelector === undefined) {
|
if (querySelector === undefined) {
|
||||||
form = <HTMLFormElement>document.querySelector('form');
|
form = <HTMLFormElement>document.querySelector("form");
|
||||||
}
|
}
|
||||||
if (typeof querySelector == 'string' || querySelector instanceof String) {
|
if (typeof querySelector == "string" || querySelector instanceof String) {
|
||||||
form = <HTMLFormElement>document.querySelector(querySelector.toString());
|
form = <HTMLFormElement>document.querySelector(querySelector.toString());
|
||||||
}
|
}
|
||||||
if (querySelector instanceof HTMLFormElement) {
|
if (querySelector instanceof HTMLFormElement) {
|
||||||
|
@ -15,22 +15,22 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import isBlankString from './isBlankString';
|
import isBlankString from "./isBlankString";
|
||||||
import {mockAlert} from '../setUpTests';
|
import {mockAlert} from "../setUpTests";
|
||||||
|
|
||||||
|
|
||||||
import setup from '../components/error/setUpTests';
|
import setup from "../components/error/setUpTests";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
mockAlert();
|
mockAlert();
|
||||||
|
|
||||||
it('getFromUrl workds', () => {
|
it("getFromUrl workds", () => {
|
||||||
document.querySelector('body').appendChild(setup());
|
document.querySelector("body").appendChild(setup());
|
||||||
expect(isBlankString('test', 'username')).toBe(false);
|
expect(isBlankString("test", "username")).toBe(false);
|
||||||
try {
|
try {
|
||||||
isBlankString(' ', 'username');
|
isBlankString(" ", "username");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toContain(`can't be empty`);
|
expect(e.message).toContain("can't be empty");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import createError from '../components/error/';
|
import createError from "../components/error/";
|
||||||
|
|
||||||
const isBlankString = (value: string|number, field: string, event?: Event) => {
|
const isBlankString = (value: string|number, field: string, event?: Event): boolean => {
|
||||||
value = value.toString();
|
value = value.toString();
|
||||||
if (!value.replace(/\s/g, '').length) {
|
if (!value.replace(/\s/g, "").length) {
|
||||||
if (event !== undefined) {
|
if (event !== undefined) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import isNumber from './isNumber';
|
import isNumber from "./isNumber";
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
it('getFromUrl workds', () => {
|
it("getFromUrl workds", () => {
|
||||||
expect(isNumber('test')).toBe(false);
|
expect(isNumber("test")).toBe(false);
|
||||||
expect(isNumber('1test213')).toBe(false);
|
expect(isNumber("1test213")).toBe(false);
|
||||||
|
|
||||||
expect(isNumber('12')).toBe(true);
|
expect(isNumber("12")).toBe(true);
|
||||||
expect(isNumber(2)).toBe(true);
|
expect(isNumber(2)).toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const isNumber = (value: string|number) => {
|
const isNumber = (value: string|number): boolean => {
|
||||||
value = value.toString();
|
value = value.toString();
|
||||||
return /^\d+$/.test(value);
|
return /^\d+$/.test(value);
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,7 @@ class LazyElement {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get() {
|
get(): HTMLElement {
|
||||||
if (this.element === null || this.element === undefined) {
|
if (this.element === null || this.element === undefined) {
|
||||||
const element = document.getElementById(this.id);
|
const element = document.getElementById(this.id);
|
||||||
if (element === null || element === undefined) {
|
if (element === null || element === undefined) {
|
||||||
|
@ -16,20 +16,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const ROUTES = {
|
const ROUTES = {
|
||||||
registerUser: '/join/',
|
registerUser: "/join/",
|
||||||
loginUser: '/login/',
|
loginUser: "/login/",
|
||||||
signoutUser: '/api/v1/signout',
|
signoutUser: "/api/v1/signout",
|
||||||
panelHome: '/',
|
panelHome: "/",
|
||||||
settings: '/settings/',
|
settings: "/settings/",
|
||||||
updateSecret: '/settings/secret/update/',
|
updateSecret: "/settings/secret/update/",
|
||||||
deleteAccount: '/settings/account/delete/',
|
deleteAccount: "/settings/account/delete/",
|
||||||
docsHome: '/docs/',
|
docsHome: "/docs/",
|
||||||
notifications: '/notifications',
|
notifications: "/notifications",
|
||||||
listSitekey: '/sitekeys/',
|
listSitekey: "/sitekeys/",
|
||||||
viewSitekey: (key: string) => `/sitekey/${key}/`,
|
viewSitekey: (key: string): string => `/sitekey/${key}/`,
|
||||||
editSitekey: (key: string) => `/sitekey/${key}/edit/`,
|
editSitekey: (key: string): string => `/sitekey/${key}/edit/`,
|
||||||
deleteSitekey: (key: string) => `/sitekey/${key}/delete/`,
|
deleteSitekey: (key: string): string => `/sitekey/${key}/delete/`,
|
||||||
addSiteKey: '/sitekeys/add',
|
addSiteKey: "/sitekeys/add",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ROUTES;
|
export default ROUTES;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import './main.scss';
|
import "./main.scss";
|
||||||
//import prove from './runner/prove';
|
//import prove from './runner/prove';
|
||||||
//import fetchPoWConfig from './runner/fetchPoWConfig';
|
//import fetchPoWConfig from './runner/fetchPoWConfig';
|
||||||
//import sendWork from './runner/sendWork';
|
//import sendWork from './runner/sendWork';
|
||||||
|
@ -8,19 +8,19 @@
|
|||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
import LazyElement from '../../utils/lazyElement';
|
import LazyElement from "../../utils/lazyElement";
|
||||||
|
|
||||||
/** mcaptcha checkbox ID **/
|
/** mcaptcha checkbox ID **/
|
||||||
export const btnId = 'widget__verification-checkbox';
|
export const btnId = "widget__verification-checkbox";
|
||||||
|
|
||||||
/** get sitekey */
|
/** get sitekey */
|
||||||
export const sitekey = () => {
|
export const sitekey = (): string => {
|
||||||
let sitekey;
|
let sitekey;
|
||||||
return (() => {
|
return (() => {
|
||||||
if (sitekey === null || sitekey === undefined) {
|
if (sitekey === null || sitekey === undefined) {
|
||||||
sitekey = new URL(window.location.href).searchParams.get('sitekey');
|
sitekey = new URL(window.location.href).searchParams.get("sitekey");
|
||||||
if (sitekey === null || sitekey === undefined) {
|
if (sitekey === null || sitekey === undefined) {
|
||||||
throw new Error(`Define sitekey in query parameter`);
|
throw new Error("Define sitekey in query parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sitekey;
|
return sitekey;
|
||||||
@ -29,8 +29,8 @@ export const sitekey = () => {
|
|||||||
|
|
||||||
/** mCaptcha API routes */
|
/** mCaptcha API routes */
|
||||||
export const ROUTES = (() => {
|
export const ROUTES = (() => {
|
||||||
const getConfig = '/api/v1/pow/config';
|
const getConfig = "/api/v1/pow/config";
|
||||||
const verififyPoW = '/api/v1/pow/verify';
|
const verififyPoW = "/api/v1/pow/verify";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/** get URL to fetch PoW configuration */
|
/** get URL to fetch PoW configuration */
|
||||||
@ -41,24 +41,31 @@ export const ROUTES = (() => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
/** get mCaptcha verifify checkbox button */
|
/** get mCaptcha verifify checkbox button */
|
||||||
export const btn = () => {
|
export const btn = (): HTMLInputElement => {
|
||||||
let btn;
|
let btn;
|
||||||
return (() => {
|
return (() => {
|
||||||
if (btn === null || btn === undefined) {
|
if (btn === null || btn === undefined) {
|
||||||
btn = <HTMLInputElement>document.getElementById(btnId);
|
btn = <HTMLInputElement>document.getElementById(btnId);
|
||||||
if (btn === null || btn === undefined) {
|
if (btn === null || btn === undefined) {
|
||||||
throw new Error(`mCaptcha button not found)`);
|
throw new Error("mCaptcha button not found)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return btn;
|
return btn;
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const messageText = () => {
|
type messageTextReturn = {
|
||||||
const beforeID = 'widget__verification-text--before';
|
before: () => void;
|
||||||
const duringID = 'widget__verification-text--during';
|
after: () => void;
|
||||||
const errorID = 'widget__verification-text--error';
|
during: () => void;
|
||||||
const afterID = 'widget__verification-text--after';
|
error: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const messageText = (): messageTextReturn => {
|
||||||
|
const beforeID = "widget__verification-text--before";
|
||||||
|
const duringID = "widget__verification-text--during";
|
||||||
|
const errorID = "widget__verification-text--error";
|
||||||
|
const afterID = "widget__verification-text--after";
|
||||||
|
|
||||||
const before = new LazyElement(beforeID);
|
const before = new LazyElement(beforeID);
|
||||||
const after = new LazyElement(afterID);
|
const after = new LazyElement(afterID);
|
||||||
@ -70,9 +77,9 @@ export const messageText = () => {
|
|||||||
// let error: HTMLElement;
|
// let error: HTMLElement;
|
||||||
|
|
||||||
/** runner fn to display HTMLElement **/
|
/** runner fn to display HTMLElement **/
|
||||||
const showMsg = (e: HTMLElement) => (e.style.display = 'block');
|
const showMsg = (e: HTMLElement) => (e.style.display = "block");
|
||||||
/** runner fn to hide HTMLElement **/
|
/** runner fn to hide HTMLElement **/
|
||||||
const hideMsg = (e: HTMLElement) => (e.style.display = 'none');
|
const hideMsg = (e: HTMLElement) => (e.style.display = "none");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/** display "before" message **/
|
/** display "before" message **/
|
||||||
@ -109,4 +116,4 @@ export const messageText = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const inputId = 'mcaptcha-response';
|
export const inputId = "mcaptcha-response";
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import genJsonPayload from './utils/genJsonPayload';
|
import genJsonPayload from "../../utils/genJsonPayload";
|
||||||
import * as CONST from './const';
|
import * as CONST from "./const";
|
||||||
|
|
||||||
type GetConfigPayload = {
|
type GetConfigPayload = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -26,8 +26,7 @@ export type PoWConfig = {
|
|||||||
* fetch proof-of-work configuration
|
* fetch proof-of-work configuration
|
||||||
* @returns {PoWConfig} pow config
|
* @returns {PoWConfig} pow config
|
||||||
* */
|
* */
|
||||||
export const fetchPoWConfig = async () => {
|
export const fetchPoWConfig = async (): Promise<PoWConfig> => {
|
||||||
try {
|
|
||||||
const payload: GetConfigPayload = {
|
const payload: GetConfigPayload = {
|
||||||
key: CONST.sitekey(),
|
key: CONST.sitekey(),
|
||||||
};
|
};
|
||||||
@ -40,9 +39,6 @@ export const fetchPoWConfig = async () => {
|
|||||||
const err = await res.json();
|
const err = await res.json();
|
||||||
throw new Error(err);
|
throw new Error(err);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default fetchPoWConfig;
|
export default fetchPoWConfig;
|
||||||
|
@ -9,26 +9,26 @@
|
|||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import prove from './prove';
|
import prove from "./prove";
|
||||||
import fetchPoWConfig from './fetchPoWConfig';
|
import fetchPoWConfig from "./fetchPoWConfig";
|
||||||
import sendWork from './sendWork';
|
import sendWork from "./sendWork";
|
||||||
import sendToParent from './sendToParent';
|
import sendToParent from "./sendToParent";
|
||||||
import * as CONST from './const';
|
import * as CONST from "./const";
|
||||||
|
|
||||||
import '../main.scss';
|
import "../main.scss";
|
||||||
|
|
||||||
let LOCK = false;
|
let LOCK = false;
|
||||||
|
|
||||||
/** add mcaptcha widget element to DOM */
|
/** add mcaptcha widget element to DOM */
|
||||||
export const registerVerificationEventHandler = () => {
|
export const registerVerificationEventHandler = (): void => {
|
||||||
const verificationContainer = <HTMLElement>(
|
const verificationContainer = <HTMLElement>(
|
||||||
document.querySelector('.widget__verification-container')
|
document.querySelector(".widget__verification-container")
|
||||||
);
|
);
|
||||||
verificationContainer.style.display = 'flex';
|
verificationContainer.style.display = "flex";
|
||||||
CONST.btn().addEventListener('click', e => solveCaptchaRunner(e));
|
CONST.btn().addEventListener("click", (e) => solveCaptchaRunner(e));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const solveCaptchaRunner = async (e: Event) => {
|
export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
||||||
if (LOCK) {
|
if (LOCK) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {gen_pow} from 'mcaptcha-browser';
|
import { gen_pow } from "mcaptcha-browser";
|
||||||
import {PoWConfig} from './fetchPoWConfig';
|
import { PoWConfig } from "./fetchPoWConfig";
|
||||||
import * as CONST from './const';
|
import * as CONST from "./const";
|
||||||
|
|
||||||
export type Work = {
|
export type Work = {
|
||||||
result: string;
|
result: string;
|
||||||
@ -30,12 +30,11 @@ type WasmWork = {
|
|||||||
* @param {PoWConfig} config - the proof-of-work configuration using which
|
* @param {PoWConfig} config - the proof-of-work configuration using which
|
||||||
* work needs to be computed
|
* work needs to be computed
|
||||||
* */
|
* */
|
||||||
const prove = async (config: PoWConfig) => {
|
const prove = async (config: PoWConfig): Promise<Work> => {
|
||||||
try {
|
|
||||||
const proofString = gen_pow(
|
const proofString = gen_pow(
|
||||||
config.salt,
|
config.salt,
|
||||||
config.string,
|
config.string,
|
||||||
config.difficulty_factor,
|
config.difficulty_factor
|
||||||
);
|
);
|
||||||
const proof: WasmWork = JSON.parse(proofString);
|
const proof: WasmWork = JSON.parse(proofString);
|
||||||
|
|
||||||
@ -47,9 +46,6 @@ const prove = async (config: PoWConfig) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default prove;
|
export default prove;
|
||||||
|
@ -8,15 +8,15 @@
|
|||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
import {Token} from './sendWork';
|
import {Token} from "./sendWork";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send pow validation token as message to parant of the iframe
|
* send pow validation token as message to parant of the iframe
|
||||||
* @param {Token} token: token received from mCaptcha service
|
* @param {Token} token: token received from mCaptcha service
|
||||||
* upon successful PoW validation
|
* upon successful PoW validation
|
||||||
* */
|
* */
|
||||||
export const sendToParent = (token: Token) => {
|
export const sendToParent = (token: Token): void => {
|
||||||
window.parent.postMessage(token, '*');
|
window.parent.postMessage(token, "*");
|
||||||
// TODO set origin. Make parent send origin as query parameter
|
// TODO set origin. Make parent send origin as query parameter
|
||||||
// or as a message to iframe
|
// or as a message to iframe
|
||||||
};
|
};
|
||||||
|
@ -9,19 +9,19 @@
|
|||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import genJsonPayload from './utils/genJsonPayload';
|
import genJsonPayload from "../../utils/genJsonPayload";
|
||||||
import * as CONST from './const';
|
import * as CONST from "./const";
|
||||||
import {Work} from './prove';
|
import {Work} from "./prove";
|
||||||
|
|
||||||
export type Token = {
|
export type Token = {
|
||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sendWork = async (payload: Work) => {
|
export const sendWork = async (payload: Work): Promise<Token> => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(CONST.ROUTES.verififyPoW, genJsonPayload(payload));
|
const res = await fetch(CONST.ROUTES.verififyPoW, genJsonPayload(payload));
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
console.debug('work verified');
|
console.debug("work verified");
|
||||||
const token: Token = await res.json();
|
const token: Token = await res.json();
|
||||||
console.debug(`token ${token.token}`);
|
console.debug(`token ${token.token}`);
|
||||||
return token;
|
return token;
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
import * as CONST from '../const';
|
import * as CONST from "../const";
|
||||||
|
|
||||||
import {getBaseHtml, sitekey, checkbox} from './setupTests';
|
import {getBaseHtml, sitekey, checkbox} from "./setupTests";
|
||||||
import * as TESTElements from './setupTests';
|
import * as TESTElements from "./setupTests";
|
||||||
|
|
||||||
it('const works', () => {
|
it("const works", () => {
|
||||||
const body = document.querySelector('body');
|
const body = document.querySelector("body");
|
||||||
const container = getBaseHtml();
|
const container = getBaseHtml();
|
||||||
body.appendChild(container);
|
body.appendChild(container);
|
||||||
expect(CONST.sitekey()).toBe(sitekey);
|
expect(CONST.sitekey()).toBe(sitekey);
|
||||||
@ -22,29 +22,29 @@ it('const works', () => {
|
|||||||
|
|
||||||
// display after
|
// display after
|
||||||
CONST.messageText().after();
|
CONST.messageText().after();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe('block');
|
expect(TESTElements.afterMsg.style.display).toBe("block");
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe('none');
|
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.duringMsg.style.display).toBe('none');
|
expect(TESTElements.duringMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.errorMsg.style.display).toBe('none');
|
expect(TESTElements.errorMsg.style.display).toBe("none");
|
||||||
|
|
||||||
// display before
|
// display before
|
||||||
CONST.messageText().before();
|
CONST.messageText().before();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe('none');
|
expect(TESTElements.afterMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe('block');
|
expect(TESTElements.beforeMsg.style.display).toBe("block");
|
||||||
expect(TESTElements.duringMsg.style.display).toBe('none');
|
expect(TESTElements.duringMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.errorMsg.style.display).toBe('none');
|
expect(TESTElements.errorMsg.style.display).toBe("none");
|
||||||
|
|
||||||
// display during
|
// display during
|
||||||
CONST.messageText().during();
|
CONST.messageText().during();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe('none');
|
expect(TESTElements.afterMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe('none');
|
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.duringMsg.style.display).toBe('block');
|
expect(TESTElements.duringMsg.style.display).toBe("block");
|
||||||
expect(TESTElements.errorMsg.style.display).toBe('none');
|
expect(TESTElements.errorMsg.style.display).toBe("none");
|
||||||
|
|
||||||
// display error
|
// display error
|
||||||
CONST.messageText().error();
|
CONST.messageText().error();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe('none');
|
expect(TESTElements.afterMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe('none');
|
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.duringMsg.style.display).toBe('none');
|
expect(TESTElements.duringMsg.style.display).toBe("none");
|
||||||
expect(TESTElements.errorMsg.style.display).toBe('block');
|
expect(TESTElements.errorMsg.style.display).toBe("block");
|
||||||
});
|
});
|
||||||
|
@ -8,28 +8,28 @@
|
|||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
*/
|
*/
|
||||||
import * as CONST from '../const';
|
import * as CONST from "../const";
|
||||||
|
|
||||||
export const sitekey = 'imbatman';
|
export const sitekey = "imbatman";
|
||||||
|
|
||||||
export const checkbox = <HTMLInputElement>document.createElement('input');
|
export const checkbox = <HTMLInputElement>document.createElement("input");
|
||||||
checkbox.type = 'checkbox';
|
checkbox.type = "checkbox";
|
||||||
checkbox.id = CONST.btnId;
|
checkbox.id = CONST.btnId;
|
||||||
|
|
||||||
const getMessages = (state: string) => {
|
const getMessages = (state: string) => {
|
||||||
const msg = <HTMLElement>document.createElement('span');
|
const msg = <HTMLElement>document.createElement("span");
|
||||||
msg.id = `widget__verification-text--${state}`;
|
msg.id = `widget__verification-text--${state}`;
|
||||||
return msg;
|
return msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const beforeMsg = getMessages('before');
|
export const beforeMsg = getMessages("before");
|
||||||
export const afterMsg = getMessages('after');
|
export const afterMsg = getMessages("after");
|
||||||
export const duringMsg = getMessages('during');
|
export const duringMsg = getMessages("during");
|
||||||
export const errorMsg = getMessages('error');
|
export const errorMsg = getMessages("error");
|
||||||
|
|
||||||
/** get base HTML with empty mCaptcha container */
|
/** get base HTML with empty mCaptcha container */
|
||||||
export const getBaseHtml = () => {
|
export const getBaseHtml = (): HTMLFormElement => {
|
||||||
const form = <HTMLFormElement>document.createElement('form');
|
const form = <HTMLFormElement>document.createElement("form");
|
||||||
form.appendChild(checkbox);
|
form.appendChild(checkbox);
|
||||||
form.appendChild(beforeMsg);
|
form.appendChild(beforeMsg);
|
||||||
form.appendChild(duringMsg);
|
form.appendChild(duringMsg);
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* mCaptcha is a PoW based DoS protection software.
|
|
||||||
* This is the frontend web component of the mCaptcha system
|
|
||||||
* Copyright © 2021 Aravinth Manivnanan <realaravinth@batsense.net>.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by Apache 2.0 or MIT license.
|
|
||||||
* You shoud have received a copy of MIT and Apache 2.0 along with
|
|
||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import genJsonPayload from './genJsonPayload';
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
username: 'Jhon',
|
|
||||||
};
|
|
||||||
|
|
||||||
const value = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
};
|
|
||||||
|
|
||||||
it('getFromUrl workds', () => {
|
|
||||||
expect(genJsonPayload(payload)).toEqual(value);
|
|
||||||
});
|
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* mCaptcha is a PoW based DoS protection software.
|
|
||||||
* This is the frontend web component of the mCaptcha system
|
|
||||||
* Copyright © 2021 Aravinth Manivnanan <realaravinth@batsense.net>.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by Apache 2.0 or MIT license.
|
|
||||||
* You shoud have received a copy of MIT and Apache 2.0 along with
|
|
||||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
|
||||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const genJsonPayload = (payload: any) => {
|
|
||||||
const value = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
};
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default genJsonPayload;
|
|
Loading…
x
Reference in New Issue
Block a user