Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPWebTools.h"
24 : #include "SPWebRoot.h"
25 : #include "SPWebInputFilter.h"
26 : #include "SPWebHostComponent.h"
27 : #include "SPDbUser.h"
28 : #include "SPDbContinueToken.h"
29 : #include "SPDbQuery.h"
30 : #include "SPDbAdapter.h"
31 : #include "SPSqlHandle.h"
32 :
33 : namespace STAPPLER_VERSIONIZED stappler::web::tools {
34 :
35 275 : static String Tools_getCancelUrl(Request &rctx) {
36 275 : StringStream cancelUrl;
37 275 : bool isSecure = rctx.isSecureConnection();
38 275 : cancelUrl << (isSecure?"https":"http") << "://nobody@" << rctx.getInfo().url.host;
39 275 : auto port = rctx.getInfo().url.port;
40 275 : if (!port.empty() && ((isSecure && port != "443") || (!isSecure && port != "80"))) {
41 275 : cancelUrl << ':' << port;
42 : }
43 275 : cancelUrl << "/__server";
44 550 : return cancelUrl.str();
45 275 : }
46 :
47 75 : bool ServerGui::isRequestPermitted(Request &req) {
48 75 : _transaction = req.acquireDbTransaction();
49 75 : return _transaction ? true : false;
50 : }
51 :
52 275 : void ServerGui::defineBasics(pug::Context &exec, Request &req, db::User *u) {
53 275 : exec.set("version", Value(config::getWebserverVersionString()));
54 275 : exec.set("hasDb", Value(true));
55 275 : exec.set("setup", Value(true));
56 275 : if (u) {
57 275 : exec.set("user", true, &u->getData());
58 1925 : exec.set("auth", Value({
59 550 : pair("id", Value(u->getObjectId())),
60 550 : pair("name", Value(u->getString("name"))),
61 550 : pair("cancel", Value(Tools_getCancelUrl(req)))
62 1100 : }));
63 :
64 275 : req.performWithStorage([&] (const db::Transaction &t) {
65 275 : exec.set("dbName", Value(t.getAdapter().getBackendInterface()->getDatabaseName()));
66 275 : return true;
67 : });
68 :
69 275 : Value components;
70 550 : for (auto &it : req.host().getComponents()) {
71 1375 : components.addValue(Value({
72 550 : pair("name", Value(it.second->getName())),
73 550 : pair("version", Value(it.second->getVersion())),
74 825 : }));
75 : }
76 275 : exec.set("components", move(components));
77 275 : exec.set("root", Value(req.host().getHostInfo().documentRoot));
78 275 : }
79 275 : }
80 :
81 75 : Status ServerGui::onTranslateName(Request &rctx) {
82 75 : if (rctx.getInfo().queryData.getBool("auth")) {
83 0 : if (rctx.getAuthorizedUser()) {
84 0 : return rctx.redirectTo(rctx.getInfo().url.path);
85 : } else {
86 0 : return HTTP_UNAUTHORIZED;
87 : }
88 : }
89 :
90 75 : if (rctx.getInfo().method == RequestMethod::Get) {
91 50 : auto userScheme = rctx.host().getUserScheme();
92 50 : size_t count = 0;
93 50 : bool hasDb = false;
94 50 : if (userScheme) {
95 50 : count = userScheme->count(_transaction);
96 50 : hasDb = true;
97 : }
98 50 : rctx.runPug("virtual://html/server.pug", [&] (pug::Context &exec, const pug::Template &) -> bool {
99 50 : exec.set("count", Value(count));
100 50 : if (auto u = rctx.getAuthorizedUser()) {
101 25 : defineBasics(exec, rctx, u);
102 :
103 25 : auto root = Root::getCurrent();
104 25 : auto stat = root->getStat();
105 :
106 25 : StringStream ret;
107 25 : ret << "\nResource stat:\n";
108 25 : ret << "\tRequests recieved: " << stat.requestsReceived << "\n";
109 25 : ret << "\tHeartbeat counter: " << stat.heartbeatCounter << "\n";
110 25 : ret << "\tDB queries performed: " << stat.dbQueriesPerformed << " (" << stat.dbQueriesReleased << " " << stat.dbQueriesPerformed - stat.dbQueriesReleased << ")\n";
111 25 : ret << "\n";
112 :
113 25 : exec.set("resStat", Value(ret.str()));
114 25 : } else {
115 25 : exec.set("setup", Value(count != 0));
116 25 : exec.set("hasDb", Value(hasDb));
117 25 : exec.set("version", Value(config::getWebserverVersionString()));
118 : }
119 :
120 50 : return true;
121 : });
122 50 : return DONE;
123 : } else {
124 25 : return DataHandler::onPostReadRequest(rctx);
125 : }
126 : return DECLINED;
127 : }
128 :
129 25 : void ServerGui::onFilterComplete(InputFilter *filter) {
130 25 : const auto data = filter->getData();
131 25 : Request rctx(filter->getRequest());
132 25 : _filter = filter;
133 :
134 25 : auto &name = data.getString("name");
135 25 : auto &passwd = data.getString("passwd");
136 25 : if (!name.empty() && !passwd.empty()) {
137 25 : _transaction.performAsSystem([&, this] () -> bool {
138 25 : return db::User::setup(_transaction, name, passwd) != nullptr;
139 : });
140 : }
141 :
142 25 : rctx.redirectTo(rctx.getInfo().unparserUri);
143 25 : rctx.setStatus(HTTP_SEE_OTHER);
144 25 : }
145 :
146 : }
|