daster/source/daster.d

469 lines
14 KiB
D
Raw Normal View History

module daster;
import vibe.vibe;
import singlog;
import readconf;
import core.stdc.stdlib : exit, EXIT_SUCCESS, EXIT_FAILURE;
import std.stdio: writefln;
import std.getopt;
import std.file;
import std.path;
import std.algorithm;
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__);
}
2023-06-04 21:35:45 +00:00
void page404(HTTPServerRequest req, HTTPServerResponse res, HTTPServerErrorInfo error) {
res.render!("404.dt", req, error);
}
int main(string[] args) {
log.level(log.INFORMATION)
.output(log.SYSLOG)
.color(true);
bool flagVersion;
string flagSettings;
try {
auto opt = getopt(
args,
config.bundling,
config.caseSensitive,
"settings|s",
"<файл> Путь к файлу конфигурации settings.conf",
&flagSettings,
"version|v",
"Текущая версия программы",
&flagVersion
);
if (opt.helpWanted) {
showVersion();
defaultGetoptPrinter(
"Использование: daster [ОПЦИИ]...\n",
opt.options
);
return EXIT_SUCCESS;
}
if (flagVersion) {
showVersion();
return EXIT_SUCCESS;
}
} catch (GetOptException e) {
showVersion();
log.c(e.msg);
log.i("Попробуйте 'daster -h' для дополнительной информации");
log.i("https://git.zhirov.kz/alexander/daster");
return EXIT_FAILURE;
}
if (!flagSettings.length)
flagSettings = "./settings.conf";
if (!flagSettings.exists) {
log.c("Файл конфигурации не найден: " ~ flagSettings);
exit(1);
}
rc.read(flagSettings);
auto webHost = rcWebHost();
serverInfo = ServerInfo(webHost.title);
if (webHost.loglevel != -1) log.level(webHost.loglevel);
if (webHost.logoutput) log.output(webHost.logoutput);
if (webHost.logfile.length) log.file(webHost.logfile);
rcAsteriskDB();
rcAuth();
auto router = new URLRouter;
router.post("/", &postReq);
router.get("/", &getReq);
router.get("*", serveStaticFiles(buildPath(webHost.data, "public")));
router.get("*", serveStaticFiles(buildPath(webHost.data, "images")));
router.get("*", serveStaticFiles(buildPath(webHost.data, "js")));
router.get("*", serveStaticFiles(buildPath(webHost.data, "jq")));
auto memorySessionStore = new MemorySessionStore;
auto settingsHTTP = new HTTPServerSettings;
auto settingsHTTPS = new HTTPServerSettings;
if (webHost.http) {
2023-06-04 21:35:45 +00:00
settingsHTTP.errorPageHandler = toDelegate(&page404);
settingsHTTP.sessionStore = memorySessionStore;
settingsHTTP.port = webHost.http;
settingsHTTP.bindAddresses = ["::1"] ~ webHost.addresses;
}
if (webHost.https) {
2023-06-04 21:35:45 +00:00
settingsHTTPS.errorPageHandler = toDelegate(&page404);
settingsHTTPS.sessionStore = memorySessionStore;
settingsHTTPS.port = webHost.https;
settingsHTTPS.bindAddresses = ["::1"] ~ webHost.addresses;
settingsHTTPS.tlsContext = createTLSContext(TLSContextKind.server);
settingsHTTPS.tlsContext.useCertificateChainFile(webHost.cert);
settingsHTTPS.tlsContext.usePrivateKeyFile(webHost.key);
}
startWebServer(webHost, settingsHTTP, settingsHTTPS, router);
return EXIT_SUCCESS;
}
void startWebServer(WebHost wh, HTTPServerSettings http, HTTPServerSettings https, URLRouter router)
{
if (wh.http && wh.https) {
auto listenerHTTP = listenHTTP(http, router);
auto listenerHTTPS = listenHTTP(https, router);
scope (exit) { listenerHTTP.stopListening(); }
scope (exit) { listenerHTTPS.stopListening(); }
runApplication();
} else if (wh.http) {
auto listenerHTTP = listenHTTP(http, router);
scope (exit) { listenerHTTP.stopListening(); }
runApplication();
} else if (wh.https) {
auto listenerHTTPS = listenHTTP(https, router);
scope (exit) { listenerHTTPS.stopListening(); }
runApplication();
}
}
void getReq(HTTPServerRequest req, HTTPServerResponse res) {
if (req.session) {
auto user = req.session.get!UserData("user");
if (user.login) {
renderMainPage(req, res);
return;
}
}
render!("authorization.dt", serverInfo)(res);
}
void renderMainPage(HTTPServerRequest req, HTTPServerResponse res) {
render!("index.dt", serverInfo)(res);
}
void postReq(HTTPServerRequest req, HTTPServerResponse res) {
if (req.method != HTTPMethod.POST) return;
auto jsr = req.json;
string query = jsr["query"].get!string;
if (query.empty) return;
if (query != "login" && !checkAuth(req)) {
res.send(
true,
"Сессия не существует. Перезагрузите страницу"
);
return;
}
log.d("%s: json request %s".format(req.clientAddress.toAddressString(), jsr.to!string));
switch (query) {
case "login":
login(req, res, serverAuthData);
break;
case "logout":
logout(req, res);
break;
case "listnumbergroups":
getListNumberGroups(req, res);
break;
case "listgroupnumbers":
getListGroupNumbers(req, res);
break;
case "viewnumber":
getViewNumber(req, res);
break;
case "addnumber":
getAddNumber(req, res);
break;
case "writenumber":
sendWriteNumber(req, res);
break;
case "updatenumber":
sendUpdateNumber(req, res);
break;
case "delnumber":
sendDelNumber(req, res);
break;
case "listsmsgroups":
getListSMSGroups(req, res);
break;
case "listgroupsms":
getListGroupSMS(req, res);
break;
case "viewsms":
getViewSMS(req, res);
break;
case "delsms":
sendDelSMS(req, res);
break;
case "listussdgroups":
getListUSSDGroups(req, res);
break;
case "listgroupussd":
getListGroupUSSD(req, res);
break;
case "viewussd":
getViewUSSD(req, res);
break;
case "delussd":
sendDelUSSD(req, res);
break;
case "serverinfo":
getServerInfo(req, res);
break;
case "writeserverinfo":
sendWriteServerInfo(req, res);
break;
default:
res.redirect("/");
}
}
void rcAsteriskDB() {
ConfigSection asteriskDB;
try {
asteriskDB = rc[]["daster-db"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки daster-db");
exit(1);
}
if (asteriskDB["host"].empty) {
log.c("В конфигурационном файле не верны настройки daster-db.host");
exit(1);
}
if (asteriskDB["port"].empty) {
log.c("В конфигурационном файле не верны настройки daster-db.port");
exit(1);
}
if (asteriskDB["dbname"].empty) {
log.c("В конфигурационном файле не верны настройки daster-db.dbname");
exit(1);
}
if (asteriskDB["user"].empty) {
log.c("В конфигурационном файле не верны настройки daster-db.user");
exit(1);
}
try {
pgsql(
"hostaddr=" ~ asteriskDB["host"] ~
" port=" ~ asteriskDB["port"] ~
" dbname=" ~ asteriskDB["dbname"] ~
" user=" ~ asteriskDB["user"] ~
" password=" ~ asteriskDB["password"]
);
} catch (Exception e) {
log.c(e.msg);
exit(1);
}
}
WebHost rcWebHost() {
WebHost wh;
ConfigSection webHost;
try {
webHost = rc[]["web-host"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host");
exit(1);
}
if (webHost["addresses"].empty) {
log.c("В конфигурационном файле не верны настройки web-host.addresses");
exit(1);
}
try {
wh.addresses = webHost["addresses"].to!string.split(',').map!(a => a.strip).array;
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.addresses");
exit(1);
}
if (webHost["http"].empty && webHost["https"].empty) {
log.c("В конфигурационном файле не верны настройки web-host.[http|https]:
должен быть указан хотя бы один протокол");
exit(1);
}
if (!webHost["http"].empty) {
try {
wh.http = webHost["http"].to!ushort;
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.http");
exit(1);
}
}
if (!webHost["https"].empty) {
try {
wh.https = webHost["https"].to!ushort;
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.https");
exit(1);
}
}
if (!webHost["https"].empty) {
if (webHost["cert"].empty || webHost["key"].empty) {
log.c("В конфигурационном файле не верны настройки web-host.[cert|key]:
необходимо указать сертификат и ключ для использования https протокола"
);
exit(1);
}
}
try {
wh.cert = webHost["cert"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.cert");
exit(1);
}
try {
wh.key = webHost["key"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.key");
exit(1);
}
if (!webHost["data"].empty) {
string data;
try {
data = webHost["data"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.data");
exit(1);
}
if (data.exists) {
if (!buildPath(data, "public").exists) {
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: public");
exit(1);
}
if (!buildPath(data, "js").exists) {
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: js");
exit(1);
}
if (!buildPath(data, "images").exists) {
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: images");
exit(1);
}
} else {
log.c("В конфигурационном файле не верны настройки web-host.data - каталог не существует: " ~ data);
exit(1);
}
wh.data = data;
}
if (!webHost["title"].empty) {
try {
wh.title = webHost["title"];
} catch (Exception e) {
log.w("Заголовок не был установлен - web-host.title");
}
}
if (!webHost["loglevel"].empty) {
try {
wh.loglevel = webHost["loglevel"].to!int;
if (wh.loglevel < 0 || wh.loglevel > 6)
throw new Exception("несуществующий уровень");
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.loglevel: " ~ e.msg);
exit(1);
}
}
if (!webHost["logoutput"].empty) {
try {
wh.logoutput = webHost["logoutput"]
.to!string.split(',')
.map!((a) {
auto flag = a.strip.to!int;
if ([1, 2, 4].canFind(flag))
return flag;
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
exit(1);
})
.fold!((a, b) => a | b);
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.logoutput");
exit(1);
}
if (wh.logoutput & 4) {
if (webHost["logfile"].empty) {
log.c("В конфигурационном файле не верны настройки web-host.logfile");
exit(1);
}
try {
wh.logfile = webHost["logfile"];
} catch (Exception e) {
log.c("В конфигурационном файле не верны настройки web-host.logfile");
exit(1);
}
}
}
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"];
}