v0.0.10
+ Добавлена авторизация как отдельная страница + Небольшие исправления в JS при ответе от сервера
This commit is contained in:
		
							parent
							
								
									639118f781
								
							
						
					
					
						commit
						e74c0a1af0
					
				
					 11 changed files with 283 additions and 40 deletions
				
			
		
							
								
								
									
										4
									
								
								dub.json
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								dub.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,9 +5,9 @@
 | 
			
		|||
    "copyright": "Copyright © 2023, Alexander Zhirov",
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "vibe-d": "~>0.9",
 | 
			
		||||
        "singlog": "~>0.3.2",
 | 
			
		||||
        "singlog": "~>0.4.0",
 | 
			
		||||
        "arsd-official:postgres": "~>10.9.10",
 | 
			
		||||
        "readconf": "~>0.3.1"
 | 
			
		||||
        "readconf": "~>0.4.0"
 | 
			
		||||
    },
 | 
			
		||||
    "buildTypes": {
 | 
			
		||||
        "debug": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,9 @@
 | 
			
		|||
		"mir-linux-kernel": "1.0.1",
 | 
			
		||||
		"openssl": "3.3.0",
 | 
			
		||||
		"openssl-static": "1.0.2+3.0.8",
 | 
			
		||||
		"readconf": "0.3.1",
 | 
			
		||||
		"silly": "1.1.1",
 | 
			
		||||
		"singlog": "0.3.2",
 | 
			
		||||
		"readconf": "0.4.0",
 | 
			
		||||
		"silly": "1.2.0-dev.2",
 | 
			
		||||
		"singlog": "0.4.0",
 | 
			
		||||
		"stdx-allocator": "2.77.5",
 | 
			
		||||
		"taggedalgebraic": "0.11.22",
 | 
			
		||||
		"vibe-core": "2.2.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								js/authorization.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								js/authorization.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
$(document).ready(function () {
 | 
			
		||||
    noticer = new Noticer;
 | 
			
		||||
 | 
			
		||||
    $("#authorization").button({ icon: "ui-icon-home" });
 | 
			
		||||
 | 
			
		||||
    $("#login, #password").on('keypress',function(e) {
 | 
			
		||||
        if(e.which == 13) {
 | 
			
		||||
            authorization()
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $("#authorization").click(() => {
 | 
			
		||||
        authorization()
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $("body").fadeTo(500, 1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function authorization() {
 | 
			
		||||
    request().then((data) => {
 | 
			
		||||
        data.error ? noticer.error(data.message) : (window.location.href = ".");
 | 
			
		||||
    }).catch((e) => {
 | 
			
		||||
        noticer.error(e.message);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function request() {
 | 
			
		||||
    let login = $("#login").val();
 | 
			
		||||
    let password = $("#password").val();
 | 
			
		||||
 | 
			
		||||
    let response = await fetch('.', {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        headers: {
 | 
			
		||||
            'Content-Type': 'application/json;charset=utf-8'
 | 
			
		||||
        },
 | 
			
		||||
        body: JSON.stringify({
 | 
			
		||||
            login: login,
 | 
			
		||||
            password: password,
 | 
			
		||||
            query: "login"
 | 
			
		||||
        })
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (!response.ok)
 | 
			
		||||
        throw new Error(`Произошла неизвестаня ошибка: ${response.status}`);
 | 
			
		||||
    
 | 
			
		||||
    const data = await response.json();
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								js/script.js
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								js/script.js
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -58,6 +58,14 @@ $(document).ready(function () {
 | 
			
		|||
        e.key == "Escape" && ($(this).val(""), lists[$("#tabs").tabs( "option", "active" )]())
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $("#logout").click(() => {
 | 
			
		||||
        request('logout', 'json').then(data => {
 | 
			
		||||
            data.error ? noticer.error(data.message) : (window.location.href = ".");
 | 
			
		||||
        }).catch(error => {
 | 
			
		||||
            noticer.error(error.message);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    loadNumbers();
 | 
			
		||||
    loadSMS();
 | 
			
		||||
    loadUSSD();
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +137,10 @@ function pEmpty(text) {
 | 
			
		|||
 | 
			
		||||
function loadNumbers() {
 | 
			
		||||
    request('listnumbergroups', 'text').then(data => {
 | 
			
		||||
        data.error ? noticer.error(data.message) : generateListNumberGroups(data);
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        else
 | 
			
		||||
            generateListNumberGroups(data);
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
        noticer.error(error.message);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -161,8 +172,8 @@ function generateListGroupNumbers(panel) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    request('listgroupnumbers', 'json', { group: panel.data("group-name") }).then(data => {
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        if (data.error)
 | 
			
		||||
            noticer.error(data.message);
 | 
			
		||||
        else {
 | 
			
		||||
            numbers = data;
 | 
			
		||||
            showListNumbers(panel);
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +358,10 @@ function delNumber(panel, currentWindow) {
 | 
			
		|||
 | 
			
		||||
function loadSMS() {
 | 
			
		||||
    request('listsmsgroups', 'text').then(data => {
 | 
			
		||||
        data.error ? noticer.error(data.message) : generateListSMSGroups(data);
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        else
 | 
			
		||||
            generateListSMSGroups(data);
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
        noticer.error(error.message);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -379,8 +393,8 @@ function generateListGroupSMS(panel) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    request('listgroupsms', 'json', { to: panel.data("to") }).then(data => {
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        if (data.error)
 | 
			
		||||
            noticer.error(data.message);
 | 
			
		||||
        else {
 | 
			
		||||
            sms = data;
 | 
			
		||||
            showListSMS(panel);
 | 
			
		||||
| 
						 | 
				
			
			@ -483,7 +497,10 @@ function delSMS(panel, currentWindow) {
 | 
			
		|||
 | 
			
		||||
function loadUSSD() {
 | 
			
		||||
    request('listussdgroups', 'text').then(data => {
 | 
			
		||||
        data.error ? noticer.error(data.message) : generateListUSSDGroups(data);
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        else
 | 
			
		||||
            generateListUSSDGroups(data);
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
        noticer.error(error.message);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -515,8 +532,8 @@ function generateListGroupUSSD(panel) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    request('listgroupussd', 'json', { to: panel.data("to") }).then(data => {
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        if (data.error)
 | 
			
		||||
            noticer.error(data.message);
 | 
			
		||||
        else {
 | 
			
		||||
            ussd = data;
 | 
			
		||||
            showListUSSD(panel);
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +635,10 @@ function delUSSD(panel, currentWindow) {
 | 
			
		|||
 | 
			
		||||
function loadServerInfo() {
 | 
			
		||||
    request('serverinfo', 'text').then(data => {
 | 
			
		||||
        data.error ? noticer.error(data.message) : showServerInfo(data);
 | 
			
		||||
        if (isJSON(data) && JSON.parse(data).error)
 | 
			
		||||
            noticer.error(JSON.parse(data).message);
 | 
			
		||||
        else
 | 
			
		||||
            showServerInfo(data);
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
        noticer.error(error.message);
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								public/authorization.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								public/authorization.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
@font-face {
 | 
			
		||||
    font-family: Scada;
 | 
			
		||||
    src: url(Scada-Regular.ttf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    height: 100vh;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    margin-top: -5%;
 | 
			
		||||
    color: #333;
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    font-family: Scada;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.form {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.div-button {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    margin-top: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    color: #333;
 | 
			
		||||
    border: 1px solid#c5c5c5;
 | 
			
		||||
    height: 30px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input:hover {
 | 
			
		||||
    border: 1px solid #999;
 | 
			
		||||
    box-shadow: 1px 1px 10px 1px #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.input-focus:focus {
 | 
			
		||||
    outline: none;
 | 
			
		||||
    box-shadow: 1px 1px 10px 1px #666;
 | 
			
		||||
    border: 1px solid #555;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.logo {
 | 
			
		||||
    background-image: url("favicon.png");
 | 
			
		||||
    min-width: 128px;
 | 
			
		||||
    min-height: 128px;
 | 
			
		||||
    background-size: contain;
 | 
			
		||||
    margin-bottom: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.title {
 | 
			
		||||
    margin: 30px;
 | 
			
		||||
    color:#333333
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.label {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    padding-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,10 @@ loglevel        => 0                                    ; 0 - debug, 1 - crit, 2
 | 
			
		|||
logoutput       => 1, 4                                 ; 1 - syslog, 2 - stout, 4 - file => example: 1,2 or 1,2,4
 | 
			
		||||
logfile         => /var/log/daster.log                  ; if log-output set with 4
 | 
			
		||||
 | 
			
		||||
[auth]
 | 
			
		||||
login           =>
 | 
			
		||||
password        =>
 | 
			
		||||
 | 
			
		||||
[daster-db]
 | 
			
		||||
host            => 127.0.0.1
 | 
			
		||||
port            => 5432
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,13 +15,16 @@ import std.array;
 | 
			
		|||
import verinfo;
 | 
			
		||||
import pgdb;
 | 
			
		||||
import structures;
 | 
			
		||||
import response;
 | 
			
		||||
 | 
			
		||||
import requests.numbers;
 | 
			
		||||
import requests.sms;
 | 
			
		||||
import requests.ussd;
 | 
			
		||||
import requests.server;
 | 
			
		||||
import requests.authorization;
 | 
			
		||||
 | 
			
		||||
static ServerInfo serverInfo;
 | 
			
		||||
static AuthData serverAuthData;
 | 
			
		||||
 | 
			
		||||
private void showVersion() {
 | 
			
		||||
    writefln("daster версия %s, собрано %s", getDasterVersion(), __DATE__);
 | 
			
		||||
| 
						 | 
				
			
			@ -32,8 +35,9 @@ void page404(HTTPServerRequest req, HTTPServerResponse res, HTTPServerErrorInfo
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int main(string[] args) {
 | 
			
		||||
    log.level(log.INFORMATION);
 | 
			
		||||
    log.output(log.SYSLOG);
 | 
			
		||||
    log.level(log.INFORMATION)
 | 
			
		||||
        .output(log.SYSLOG)
 | 
			
		||||
        .color(true);
 | 
			
		||||
 | 
			
		||||
    bool flagVersion;
 | 
			
		||||
    string flagSettings;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +92,7 @@ int main(string[] args) {
 | 
			
		|||
    if (webHost.logfile.length) log.file(webHost.logfile);
 | 
			
		||||
 | 
			
		||||
    rcAsteriskDB();
 | 
			
		||||
    rcAuth();
 | 
			
		||||
 | 
			
		||||
    auto router = new URLRouter;
 | 
			
		||||
    router.post("/", &postReq);
 | 
			
		||||
| 
						 | 
				
			
			@ -144,16 +149,15 @@ void startWebServer(WebHost wh, HTTPServerSettings http, HTTPServerSettings http
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void getReq(HTTPServerRequest req, HTTPServerResponse res) {
 | 
			
		||||
    // if (req.session) {
 | 
			
		||||
    //     auto user = req.session.get!UserData("userData");
 | 
			
		||||
    //     if (user.loggedIn) {
 | 
			
		||||
    //         renderMainPage(req, res);
 | 
			
		||||
    //         return;
 | 
			
		||||
    //     }
 | 
			
		||||
    // }
 | 
			
		||||
    if (req.session) {
 | 
			
		||||
        auto user = req.session.get!UserData("user");
 | 
			
		||||
        if (user.login) {
 | 
			
		||||
            renderMainPage(req, res);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // render!("index.dt", serverInfo)(res);
 | 
			
		||||
    renderMainPage(req, res);
 | 
			
		||||
    render!("authorization.dt", serverInfo)(res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void renderMainPage(HTTPServerRequest req, HTTPServerResponse res) {
 | 
			
		||||
| 
						 | 
				
			
			@ -168,23 +172,23 @@ void postReq(HTTPServerRequest req, HTTPServerResponse res) {
 | 
			
		|||
 | 
			
		||||
    if (query.empty) return;
 | 
			
		||||
 | 
			
		||||
    // if (query != "authorization" && !checkAuth(req)) {
 | 
			
		||||
    //     res.send(
 | 
			
		||||
    //         true,
 | 
			
		||||
    //         "Сессия не существует. Перезагрузите страницу"
 | 
			
		||||
    //     );
 | 
			
		||||
    //     return;
 | 
			
		||||
    // }
 | 
			
		||||
    if (query != "login" && !checkAuth(req)) {
 | 
			
		||||
        res.send(
 | 
			
		||||
            true,
 | 
			
		||||
            "Сессия не существует. Перезагрузите страницу"
 | 
			
		||||
        );
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log.d("json request: " ~ jsr.to!string);
 | 
			
		||||
 | 
			
		||||
    switch (query) {
 | 
			
		||||
    //     case "authorization":
 | 
			
		||||
    //         authorization(req, res);
 | 
			
		||||
    //         break;
 | 
			
		||||
    //     case "logout":
 | 
			
		||||
    //         logout(req, res);
 | 
			
		||||
    //         break;
 | 
			
		||||
        case "login":
 | 
			
		||||
            login(req, res, serverAuthData);
 | 
			
		||||
            break;
 | 
			
		||||
        case "logout":
 | 
			
		||||
            logout(req, res);
 | 
			
		||||
            break;
 | 
			
		||||
        case "listnumbergroups":
 | 
			
		||||
            getListNumberGroups(req, res);
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -441,3 +445,24 @@ WebHost rcWebHost() {
 | 
			
		|||
 | 
			
		||||
    return wh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rcAuth() {
 | 
			
		||||
    ConfigSection auth;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        auth = rc[]["auth"];
 | 
			
		||||
    } catch (Exception e) {
 | 
			
		||||
        log.c("В конфигурационном файле не верны настройки auth");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (auth["login"].empty)
 | 
			
		||||
        log.w("Логин не был установлен - auth.login");
 | 
			
		||||
    else
 | 
			
		||||
        serverAuthData.login = auth["login"];
 | 
			
		||||
 | 
			
		||||
    if (auth["password"].empty)
 | 
			
		||||
        log.w("Пароль не был установлен - auth.password");
 | 
			
		||||
    else
 | 
			
		||||
        serverAuthData.password = auth["password"];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										47
									
								
								source/requests/authorization.d
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								source/requests/authorization.d
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
module requests.authorization;
 | 
			
		||||
 | 
			
		||||
import vibe.vibe;
 | 
			
		||||
import response;
 | 
			
		||||
import structures;
 | 
			
		||||
import singlog;
 | 
			
		||||
 | 
			
		||||
void login(HTTPServerRequest req, HTTPServerResponse res, AuthData serverAuthData) {
 | 
			
		||||
    auto userAuthData = deserializeJson!AuthData(req.json);
 | 
			
		||||
 | 
			
		||||
    if (!(serverAuthData.login == userAuthData.login &&
 | 
			
		||||
        serverAuthData.password == userAuthData.password)) {
 | 
			
		||||
        log.i(("Данные авторизации не верны: %s").format(req.json));
 | 
			
		||||
        res.send(
 | 
			
		||||
            true,
 | 
			
		||||
            "Данные авторизации не верны"
 | 
			
		||||
        );
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto user = UserData(true);
 | 
			
		||||
 | 
			
		||||
    req.session = res.startSession();
 | 
			
		||||
    req.session.set!UserData("user", user);
 | 
			
		||||
 | 
			
		||||
    log.i("Авторизация успешно пройдена");
 | 
			
		||||
 | 
			
		||||
    res.send();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void logout(HTTPServerRequest req, HTTPServerResponse res) {
 | 
			
		||||
    req.session.set!UserData("user", UserData.init);
 | 
			
		||||
    res.terminateSession();
 | 
			
		||||
 | 
			
		||||
    log.i("Выход из системы");
 | 
			
		||||
 | 
			
		||||
    res.send();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool checkAuth(HTTPServerRequest req) {
 | 
			
		||||
    if (req.session)
 | 
			
		||||
        return req.session.get!UserData("user").login;
 | 
			
		||||
 | 
			
		||||
    log.d("Отсутствует авторизация");
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,6 +4,15 @@ struct ServerInfo {
 | 
			
		|||
    string name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AuthData {
 | 
			
		||||
    string login;
 | 
			
		||||
    string password;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct UserData {
 | 
			
		||||
    bool login = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct WebHost {
 | 
			
		||||
    string[] addresses;
 | 
			
		||||
    ushort http = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
module version_;
 | 
			
		||||
 | 
			
		||||
enum dasterVersion = "v0.0.9";
 | 
			
		||||
enum dasterVersion = "v0.0.10";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										26
									
								
								views/authorization.dt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								views/authorization.dt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
doctype html
 | 
			
		||||
head
 | 
			
		||||
    title #{serverInfo.name}: авторизация
 | 
			
		||||
    link(rel='icon', type='image/png', sizes='128x128', href='favicon.png')
 | 
			
		||||
    link(rel='stylesheet', type='text/css', href='jquery-ui.min.css')
 | 
			
		||||
    link(rel='stylesheet', type='text/css', href='authorization.css')
 | 
			
		||||
    script(src='jquery-3.7.0.min.js')
 | 
			
		||||
    script(src='jquery-ui.min.js')
 | 
			
		||||
    script(src='noticer.min.js')
 | 
			
		||||
    script(src='authorization.js')
 | 
			
		||||
body
 | 
			
		||||
    div.form
 | 
			
		||||
        div.logo
 | 
			
		||||
        div.title #{serverInfo.name}
 | 
			
		||||
        table
 | 
			
		||||
            tbody
 | 
			
		||||
                tr
 | 
			
		||||
                    td.label Логин:
 | 
			
		||||
                    td
 | 
			
		||||
                        input.input-focus#login(type='text')
 | 
			
		||||
                tr
 | 
			
		||||
                    td.label Пароль:
 | 
			
		||||
                    td
 | 
			
		||||
                        input.input-focus#password(type='password')
 | 
			
		||||
        div.div-button
 | 
			
		||||
            button#authorization Войти
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue