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__ << " " << std::endl;
101  std::cout << __FILE__ << ":" << __LINE__ << " " << environment().headerValue( "X-Forwarded-For" ) << std::endl;
102  for( const auto & kvp : environment().getParameterMap() )
103  for( const auto vvv : kvp.second )
104  std::cout << __FILE__ << ":" << __LINE__ << " " << kvp.first << " " << vvv << std::endl;
105 #endif
106 
107 #ifndef NEVER
108  std::cout << __FILE__ << ":" << __LINE__ << std::endl << __FILE__ << ":" << __LINE__ << " [" << Wt::WDateTime::currentDateTime().toString() << "] " << environment().clientAddress() << " " << sessionId() << " " << url() << std::endl << __FILE__ << ":" << __LINE__ << std::endl;
109 #endif
110 
111 #ifdef USE_GNUCASH_ENGINE
112  gnucash_session() .open( g_dbName );
113 #endif
114 
115 #ifdef USE_GNUCASHEW_SESSION
117 #endif
118 
119  engine().open( g_dbName );
120 
121 // showEnvironment();
122 
123  /*
124  ** Utilize the bootstrap theme.
125  **
126  */
127  auto bootstrapTheme = std::make_shared<Wt::WBootstrapTheme>();
128  bootstrapTheme-> setVersion( Wt::BootstrapVersion::v3 );
129  bootstrapTheme-> setResponsive( true );
130  setTheme( bootstrapTheme );
131  useStyleSheet( "resources/themes/bootstrap/3/bootstrap-theme.min.css" );
132  useStyleSheet( "styles/gcw.css" );
133 
134  /*
135  ** GnuCashew english language translations
136  **
137  ** Note on the 'language elements' files.
138  ** The 'files' are located in the docroot folder. The main "united states english"
139  ** translation file is called "gcw.xml". This file contains all the words used in
140  ** the system called upon by Wt::WString::tr("id value"). Each 'language' file is
141  ** therefore;
142  ** "gcw_nl.xml" Dutch (netherlands)
143  ** "gcw_sp.xml" Spanish
144  **
145  ** It is only necessary to reference the english "gcw.xml" file, and the other language
146  ** files will get loaded automatically when the language changes.
147  **
148  ** See "Gui/MainWidget.cpp" for the references to the 'langCombo' code.
149  **
150  */
151  messageResourceBundle().use( docRoot() + "/styles/gcw" ); // Language Elements
152  messageResourceBundle().use( docRoot() + "/styles/gcw_gui" ); // UI elements
153 
154  /*
155  ** set the date format to the browser.
156  **
157  */
158 #ifdef NEVER
159  auto loc = locale();
160  auto tz = date::locate_zone( environment().timeZoneName() );
161  loc.setTimeZone( tz );
162 #endif
163 
164 #ifdef USER_LOGIN
165  auto lw = root()-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
166 
167  lw-> addWidget( std::move( createAuthWidget() ) );
168 
169  m_mainContainer = lw-> addWidget( std::make_unique< Wt::WContainerWidget >(), 1 );
170 
171  /*
172  ** If the login status changes, respond to it.
173  **
174  */
175  gnucashew_session().login().changed().connect( this, &App::buildSite );
176 #endif
177 
178  /*
179  ** build the site
180  **
181  */
182  buildSite();
183 
184 #ifdef NEVER
185  for( auto & commodity : GCW::Dbo::Commodities::getIso4217Commodities() )
186  {
187  std::cout << __FILE__ << ":" << __LINE__
188  << " \t" << commodity.isocode
189  << " \t" << commodity.unitname
190  << " \t" << commodity.partname
191  << " \t" << commodity.nameSpace
192  << " \t" << commodity.exchangeCode
193  << " \t" << commodity.partsPerUnit
194  << " \t" << commodity.smallestFraction
195  << " \t" << commodity.localSymbol
196  << " \t" << commodity.fullname
197  << std::endl;
198  }
199 #endif
200 
201 } // endGCW::App::App( const Wt::WEnvironment & env )
202 
203 auto
205 showWelcome()-> void
206 {
207  Wt::WDialog dialog( TR( "gcw.welcome.title" ) );
208  dialog.rejectWhenEscapePressed( true );
209  dialog.setClosable( true );
210  dialog.contents()-> addNew< Wt::WText >( TR( "gcw.welcome.body" ) );
211  dialog.exec();
212 
213 } // endshowWelcome()-> void
214 
215 auto
217 createAuthWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
218 {
219  auto retVal = std::make_unique< Wt::Auth::AuthWidget >
220  (
222  gnucashew_session().users(),
223  gnucashew_session().login()
224  );
225 
226  retVal-> model()-> addPasswordAuth( & GCW::Dbo::Users::passwordService() );
227  retVal-> model()-> addOAuth( GCW::Dbo::Users::oService() );
228  retVal-> setRegistrationEnabled( true );
229  retVal-> processEnvironment();
230 
231  return std::move( retVal );
232 
233 } // endcreateLoginWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
234 
235 
236 auto
238 buildSite()-> void
239 {
240 #ifdef USER_LOGIN
241  std::cout << __FILE__ << ":" << __LINE__ << " " << gnucashew_session().login().loggedIn() << std::endl;
242 
243  if( m_mainWidget )
244  m_mainContainer-> removeWidget( m_mainWidget );
245 // m_mainContainer-> clear();
246 
247  std::cout << __FILE__ << ":" << __LINE__ << " " << gnucashew_session().login().loggedIn() << std::endl;
248 
249 // if( gnucashew_session().login().loggedIn() )
250 // if( true )
251  if( bookmarkUrl() == "demo" || gnucashew_session().login().loggedIn() )
252  buildLoggedIn();
253  else
254  buildLogin();
255 #else
256 
257  buildLoggedIn();
258 
259 #endif
260 
261 } // endbuildSite()-> void
262 
263 auto
265 buildLogin()-> void
266 {
267 
268 } // endbuildLogin()-> void
269 
270 auto
272 buildLoggedIn()-> void
273 {
274 
275 #ifdef USER_LOGIN
276  /*
277  ** Set a layout manager on the root widget so that everything can
278  ** be laid out correctly.
279  **
280  */
281  auto lw = m_mainContainer-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
282  lw-> setSpacing( 0 );
283 
284  /*
285  ** Build and install the main desktop widget.
286  **
287  */
288  m_mainWidget = lw-> addWidget( std::make_unique< GCW::Gui::MainWidget >() );
289 
290 #else
291 
292  /*
293  ** Set a layout manager on the root widget so that everything can
294  ** be laid out correctly.
295  **
296  */
297  auto lw = root()-> setLayout( std::make_unique< Wt::WVBoxLayout >() );
298  lw-> setSpacing( 0 );
299 
300  /*
301  ** Build and install the main desktop widget.
302  **
303  */
304  m_mainWidget = lw-> addWidget( std::make_unique< GCW::Gui::MainWidget >() );
305 
306 #endif
307 
308  /*
309  ** If this is the demo, wait a second and pop a welcome screen.
310  **
311  ** For whatever reason, just firing off this pop-up dialog at the
312  ** beginning of the program start causes the widget to not display
313  ** properly. Instead of resizing the dialog to fit the available
314  ** space in the browser, it makes a super-wide dialog with all the
315  ** text on just one line. By delaying the dialog just a bit, it
316  ** seems to mitigate this issue.
317  **
318  */
319 // if( bookmarkUrl() == "demo" )
320  if( g_dbName.find( "LorimarkSolutions" ) == std::string::npos )
321  Wt::WTimer::singleShot( std::chrono::seconds(1), this, &App::showWelcome );
322 
323  /*
324  ** If we have the gnucashew extensions, then record that we logged on.
325  **
326  */
327 // if( engine().hasGnuCashewExtensions() )
328 // {
329 // Wt::Dbo::Transaction t( gnucashew_session() );
330 // auto item = GCW::Dbo::Vars::get( "logon","sys" );
331 // item.modify()-> setVar( "logonOn", Wt::WDateTime::currentDateTime().toString( ISO_DATE_FORMAT ) );
332 // item.modify()-> setVar( "logonBy", "dev(0)" );
333 // }
334 
335 } // endbuildLoggedIn()-> void
336 
337 
338 
std::string g_dbName
Definition: main.cpp:25
Definition: App.h:26
auto buildLogin() -> void
Definition: App.cpp:265
Dbo::GnuCashew::Session & gnucashew_session()
Definition: App.h:39
Wt::WContainerWidget * m_mainContainer
Definition: App.h:60
GCW::Eng::Engine & engine()
Definition: App.h:31
auto createAuthWidget() -> std::unique_ptr< Wt::Auth::AuthWidget >
Definition: App.cpp:217
App(const Wt::WEnvironment &env)
Definition: App.cpp:72
auto buildSite() -> void
Definition: App.cpp:238
auto showWelcome() -> void
Definition: App.cpp:205
auto buildLoggedIn() -> void
Definition: App.cpp:272
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