GnuCashew ~ GnuCash Enabled Web
GCW
App.cpp
Go to the documentation of this file.
1 #line 2 "src/App.cpp"
2 
3 /*
4 ** USER_LOGIN is a switch that sets up the UI with
5 ** a user-login-widget. It's not working yet.
6 **
7 */
8 //#define USER_LOGIN
9 
10 #include <Wt/Date/tz.h>
11 #include <Wt/WBootstrapTheme.h>
12 #include <Wt/Auth/AuthWidget.h>
13 #include <Wt/WDate.h>
14 #include <Wt/WDialog.h>
15 #include <Wt/WEnvironment.h>
16 #include <Wt/WHBoxLayout.h>
17 #include <Wt/WVBoxLayout.h>
18 #include <Wt/WLocale.h>
19 #include <Wt/WServer.h>
20 #include <Wt/WText.h>
21 #include <Wt/WVBoxLayout.h>
22 
23 #include "App.h"
24 #include "Dbo/Users/Auth.h"
25 #include "GnuCashew.h"
27 
28 extern std::string g_dbName;
29 
30 namespace {
31 
32 void showEnvironment()
33 {
34  auto app = GCW::app();
35 
36  std::cout << __FILE__ << ":" << __LINE__
37  << "\n title: " << app-> title()
38  << "\n appRoot: " << app-> appRoot()
39  << "\n docRoot: " << app-> docRoot()
40  << "\n sessionId: " << app-> sessionId()
41  << "\n metaHeader: " << app-> metaHeader( Wt::MetaHeaderType::Meta, "*" )
42  << "\n bodyClass: " << app-> bodyClass()
43  << "\n htmlClass: " << app-> htmlClass()
44  << "\n url: " << app-> url()
45  << "\n bookmarkUrl: " << app-> bookmarkUrl()
46  << "\n internalPath: " << app-> internalPath()
47  << "\n javaScriptClass: " << app-> javaScriptClass()
48  << "\n resourcesUrl: " << app-> resourcesUrl()
49  << "\n r-resourcesUrl: " << app-> relativeResourcesUrl()
50  << "\n referrer: " << app-> environment().referer()
51  << "\n accept: " << app-> environment().accept()
52  << "\n X-Forwarded-For: " << app-> environment().headerValue( "X-Forwarded-For" )
53  << "\n X-Forwarded-Client: " << app-> environment().headerValue( "X-Forwarded-Client" )
54  << "\n X-Forwarded-Xyz: " << app-> environment().headerValue( "X-Forwarded-Xyz" )
55  << "\n clientAddress: " << app-> environment().clientAddress()
56  << std::endl
57  ;
58 
59  for( const auto & pair : app-> environment().getParameterMap() )
60  for( const auto & value : pair.second )
61  std::cout << __FILE__ << ":" << __LINE__ << " " << pair.first << "=" << value << std::endl;
62 
63 } // endvoid showEnvironment()
64 
65 } // endnamespace {
66 
68 {
69  return static_cast< GCW::App* >( Wt::WApplication::instance() );
70 }
71 
72 GCW::App::App( const Wt::WEnvironment & env )
73 : Wt::WApplication( env )
74 {
75  root()-> addStyleClass( "GnuCashewRoot" );
76 
77  setTitle( "GnuCashew ~ " + g_dbName );
78 
79 #ifdef NEVER
80  // something to note about the X-Forwarded-For haproxy value. This setting
81  // needs to be set within the 'haproxy.cfg haproxy_loop' section. To
82  // troubleshoot this, open the /var/log/haproxy.log file and look for the
83  // reported IP address;
84  // Oct 10 09:45:26 lsus1 haproxy[31634]: 104.28.50.130:50944 [10/Oct/2024:09:45:24.526] www-https~ haproxy_loop/haproxy_loop 0/0/1998 297 -- 6/3/2/1/0 0/0
85  // Oct 10 09:45:27 lsus1 haproxy[31634]: 127.0.0.1:43110 [10/Oct/2024:09:45:26.362] www-http gnucashew/gnucashew_wt 976/0/0/6/982 200 3777 - - ---- 6/3/0/1/0 0/0 "POST /demo?wtd=wDqiKVj7Wjibd276 HTTP/1.1"
86  // note in the first-line, haproxy_loop, the IP address noted is the actual
87  // ip address of the incoming client. this is the section that needs to
88  // carry the 'option forwardfor' setting to forward that address along to
89  // the next section;
90  // backend haproxy_loop
91  // mode http
92  // option forwardfor
93  // server haproxy_loop localhost:80
94  //
95  // note: also that the wt_config.xml file needs to posess the
96  // <behind-reverse-proxy>true</behind-reverse-proxy> value
97  // note: that the wthttp back-end does not regard the X-Forwarded-For value
98  // and therefore will report the incorrect IP address to the console
99  //
100  std::cout << __FILE__ << ":" << __LINE__ << " " << environment().headerValue( "X-Forwarded-For" ) << std::endl;
101  for( const auto & kvp : environment().getParameterMap() )
102  for( const auto vvv : kvp.second )
103  std::cout << __FILE__ << ":" << __LINE__ << " " << kvp.first << " " << vvv << std::endl;
104 #endif
105 
106 #ifndef NEVER
107  std::cout
108  << __FILE__ << ":" << __LINE__ << std::endl
109  << __FILE__ << ":" << __LINE__
110  << " [" << Wt::WDateTime::currentDateTime().toString()
111  << "] " << environment().clientAddress()
112  << " " << sessionId()
113  << " " << url() << std::endl
114  << __FILE__ << ":" << __LINE__
115  << std::endl;
116 #endif
117 
118 #ifdef USE_GNUCASH_ENGINE
119  gnucash_session() .open( g_dbName );
120 #endif
121 
122 #ifdef USE_GNUCASHEW_SESSION
124 #endif
125 
126  engine().open( g_dbName );
127 
128 // showEnvironment();
129 
130  /*
131  ** Utilize the bootstrap theme.
132  **
133  */
134  auto bootstrapTheme = std::make_shared<Wt::WBootstrapTheme>();
135  bootstrapTheme-> setVersion( Wt::BootstrapVersion::v3 );
136  bootstrapTheme-> setResponsive( true );
137  setTheme( bootstrapTheme );
138  useStyleSheet( "resources/themes/bootstrap/3/bootstrap-theme.min.css" );
139  useStyleSheet( "styles/gcw.css" );
140 
141  /*
142  ** GnuCashew english language translations
143  **
144  ** Note on the 'language elements' files.
145  ** The 'files' are located in the docroot folder. The main "united states english"
146  ** translation file is called "gcw.xml". This file contains all the words used in
147  ** the system called upon by Wt::WString::tr("id value"). Each 'language' file is
148  ** therefore;
149  ** "gcw_nl.xml" Dutch (netherlands)
150  ** "gcw_sp.xml" Spanish
151  **
152  ** It is only necessary to reference the english "gcw.xml" file, and the other language
153  ** files will get loaded automatically when the language changes.
154  **
155  ** See "Gui/MainWidget.cpp" for the references to the 'langCombo' code.
156  **
157  */
158  messageResourceBundle().use( docRoot() + "/styles/gcw" ); // Language Elements
159  messageResourceBundle().use( docRoot() + "/styles/gcw_gui" ); // UI elements
160 
161  /*
162  ** set the date format to the browser.
163  **
164  */
165 #ifdef NEVER
166  auto loc = locale();
167  auto tz = date::locate_zone( environment().timeZoneName() );
168  loc.setTimeZone( tz );
169 #endif
170 
171 #ifdef USER_LOGIN
172  auto lw = root()-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
173 
174  lw-> addWidget( std::move( createAuthWidget() ) );
175 
176  m_mainContainer = lw-> addWidget( std::make_unique< Wt::WContainerWidget >(), 1 );
177 
178  /*
179  ** If the login status changes, respond to it.
180  **
181  */
182  gnucashew_session().login().changed().connect( this, &App::buildSite );
183 #endif
184 
185  /*
186  ** build the site
187  **
188  */
189  buildSite();
190 
191 #ifdef NEVER
192  std::cout << __FILE__ << ":" << __LINE__
193  << " \tcommodity.isocode"
194  << " \tcommodity.unitname"
195  << " \tcommodity.partname"
196  << " \tcommodity.nameSpace"
197  << " \tcommodity.exchangeCode"
198  << " \tcommodity.partsPerUnit"
199  << " \tcommodity.smallestFraction"
200  << " \tcommodity.localSymbol"
201  << " \tcommodity.fullname"
202  << std::endl;
203  for( auto & commodity : GCW::Dbo::Commodities::getIso4217Commodities() )
204  {
205  std::cout << __FILE__ << ":" << __LINE__
206  << " \t" << commodity.isocode
207  << " \t" << commodity.unitname
208  << " \t" << commodity.partname
209  << " \t" << commodity.nameSpace
210  << " \t" << commodity.exchangeCode
211  << " \t" << commodity.partsPerUnit
212  << " \t" << commodity.smallestFraction
213  << " \t" << commodity.localSymbol
214  << " \t" << commodity.fullname
215  << std::endl;
216  }
217 #endif
218 
219 #ifdef SIMPLE_REPEATING_TIMER_FOR_TESTING_THINGS
220  m_timer = std::make_unique< Wt::WTimer >();
221  m_timer-> setInterval( std::chrono::seconds(1) );
222  m_timer-> start();
223  m_timer->
224  timeout().connect( [&]( Wt::WMouseEvent _event )
225  {
226  std::cout << __FILE__ << ":" << __LINE__ << " testing something..." << std::endl;
227  });
228 #endif
229 
230 } // endGCW::App::App( const Wt::WEnvironment & env )
231 
232 auto
234 showWelcome()-> void
235 {
236  Wt::WDialog dialog( TR( "gcw.welcome.title" ) );
237  dialog.rejectWhenEscapePressed( true );
238  dialog.setClosable( true );
239  dialog.contents()-> addNew< Wt::WText >( TR( "gcw.welcome.body" ) );
240  dialog.exec();
241 
242 } // endshowWelcome()-> void
243 
244 auto
246 createAuthWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
247 {
248  auto retVal = std::make_unique< Wt::Auth::AuthWidget >
249  (
251  gnucashew_session().users(),
252  gnucashew_session().login()
253  );
254 
255  retVal-> model()-> addPasswordAuth( & GCW::Dbo::Users::passwordService() );
256  retVal-> model()-> addOAuth( GCW::Dbo::Users::oService() );
257  retVal-> setRegistrationEnabled( true );
258  retVal-> processEnvironment();
259 
260  return std::move( retVal );
261 
262 } // endcreateLoginWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
263 
264 
265 auto
267 buildSite()-> void
268 {
269 #ifdef USER_LOGIN
270  std::cout << __FILE__ << ":" << __LINE__ << " " << gnucashew_session().login().loggedIn() << std::endl;
271 
272  if( m_mainWidget )
273  m_mainContainer-> removeWidget( m_mainWidget );
274 // m_mainContainer-> clear();
275 
276  std::cout << __FILE__ << ":" << __LINE__ << " " << gnucashew_session().login().loggedIn() << std::endl;
277 
278 // if( gnucashew_session().login().loggedIn() )
279 // if( true )
280  if( bookmarkUrl() == "demo" || gnucashew_session().login().loggedIn() )
281  buildLoggedIn();
282  else
283  buildLogin();
284 #else
285 
286  buildLoggedIn();
287 
288 #endif
289 
290 } // endbuildSite()-> void
291 
292 auto
294 buildLogin()-> void
295 {
296 
297 } // endbuildLogin()-> void
298 
299 auto
301 buildLoggedIn()-> void
302 {
303 
304 #ifdef USER_LOGIN
305  /*
306  ** Set a layout manager on the root widget so that everything can
307  ** be laid out correctly.
308  **
309  */
310  auto lw = m_mainContainer-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
311  lw-> setSpacing( 0 );
312 
313  /*
314  ** Build and install the main desktop widget.
315  **
316  */
317  m_mainWidget = lw-> addWidget( std::make_unique< GCW::Gui::MainWidget >() );
318 
319 #else
320 
321  /*
322  ** Set a layout manager on the root widget so that everything can
323  ** be laid out correctly.
324  **
325  */
326  auto lw = root()-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
327  lw-> setSpacing( 0 );
328 
329  /*
330  ** Build and install the main desktop widget.
331  **
332  */
333  m_mainWidget = lw-> addWidget( std::make_unique< GCW::Gui::MainWidget >() );
334 
335 #endif
336 
337  /*
338  ** If this is the demo, wait a second and pop a welcome screen.
339  **
340  ** For whatever reason, just firing off this pop-up dialog at the
341  ** beginning of the program start causes the widget to not display
342  ** properly. Instead of resizing the dialog to fit the available
343  ** space in the browser, it makes a super-wide dialog with all the
344  ** text on just one line. By delaying the dialog just a bit, it
345  ** seems to mitigate this issue.
346  **
347  */
348 // if( bookmarkUrl() == "demo" )
349  if( g_dbName.find( "LorimarkSolutions" ) == std::string::npos )
350  Wt::WTimer::singleShot( std::chrono::seconds(1), this, &App::showWelcome );
351 
352  /*
353  ** If we have the gnucashew extensions, then record that we logged on.
354  **
355  */
356 // if( engine().hasGnuCashewExtensions() )
357 // {
358 // Wt::Dbo::Transaction t( gnucashew_session() );
359 // auto item = GCW::Dbo::Vars::get( "logon","sys" );
360 // item.modify()-> setVar( "logonOn", Wt::WDateTime::currentDateTime().toString( ISO_DATE_FORMAT ) );
361 // item.modify()-> setVar( "logonBy", "dev(0)" );
362 // }
363 
364 } // endbuildLoggedIn()-> void
365 
366 
367 
std::string g_dbName
Definition: main.cpp:25
static std::unique_ptr< GCW::Gui::BillPay::PaymentWidgetDialog > dialog
Definition: EditWidget.cpp:331
Definition: App.h:26
auto buildLogin() -> void
Definition: App.cpp:294
Dbo::GnuCashew::Session & gnucashew_session()
Definition: App.h:39
Wt::WContainerWidget * m_mainContainer
Definition: App.h:60
std::unique_ptr< Wt::WTimer > m_timer
Definition: App.h:63
GCW::Eng::Engine & engine()
Definition: App.h:31
auto createAuthWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
Definition: App.cpp:246
App(const Wt::WEnvironment &env)
Definition: App.cpp:72
auto buildSite() -> void
Definition: App.cpp:267
auto showWelcome() -> void
Definition: App.cpp:234
auto buildLoggedIn() -> void
Definition: App.cpp:301
auto login() -> Wt::Auth::Login &
bool open(const std::string &_path)
Open a database.
bool open(const std::string &_filePath)
Open the Database.
Definition: Engine.cpp:19
#define TR(X)
Definition: define.h:17
auto currentDateTime() -> Wt::WDateTime
Current Date/Time.
Definition: Core.cpp:260
auto getIso4217Commodities() -> std::vector< Commodity_t >
Get Commodities.
Definition: Commodities.cpp:85
auto passwordService() -> const Wt::Auth::PasswordService &
Definition: Auth.cpp:93
auto service() -> const Wt::Auth::AuthService &
Definition: Auth.cpp:85
auto oService() -> const std::vector< const Wt::Auth::OAuthService * >
Definition: Auth.cpp:101
App * app()
Definition: App.cpp:67
Definition: GncLock.h:6