13ecc606cadb711c5f7f89178111f7272f304fe6
[nit.git] / lib / nitcorn / examples / src / xymus_net.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014-2015 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Configuration of the Web server of xymus.net
18 module xymus_net
19
20 import nitcorn
21 import privileges
22
23 # Use actions defined by contribs
24 import tnitter
25 import benitlux::benitlux_controller
26 import benitlux::benitlux_restful
27 import opportunity::opportunity_controller
28 import nitiwiki::wiki_edit
29
30 # Header for the whole site
31 class MasterHeader
32 super Template
33
34 # Current page id, is used to set the `active` class on the header tab
35 var page: nullable String
36
37 # Make room for a login or logout placeholder (used by tnitter)
38 var login_placeholder: Bool
39
40 redef fun rendering
41 do
42 var actives = new HashMap[String, String]
43 var page = page
44 if page != null then actives[page] = " class=\"active\""
45
46 add """
47 <nav class="navbar navbar-default" role="navigation">
48 <div class="container-fluid">
49 <div class="navbar-header">
50 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
51 <span class="sr-only">Toggle navigation</span>
52 <span class="icon-bar"></span>
53 <span class="icon-bar"></span>
54 <span class="icon-bar"></span>
55 </button>
56 <a class="navbar-brand" href="http://xymus.net/">Xymus.net</a>
57 </div>
58
59 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
60 <ul class="nav navbar-nav">
61 <li{{{actives.get_or_default("ens", "")}}}><a href="http://xymus.net/ens/">Enseignement</a></li>
62 <li{{{actives.get_or_default("opportunity", "")}}}>
63 <a href="http://xymus.net/opportunity/">
64 <img height="22px" src="/static/opportunity-small-fr.png"></a>
65 </li>
66 <li{{{actives.get_or_default("tnitter", "")}}}>
67 <a href="http://xymus.net/tnitter/">
68 <img height="22px" src="/static/tnitter-small.png">
69 </a></li>
70 <li><a href="http://xymus.net/pep8/">Pep/8 Analysis</a></li>
71 <li{{{actives.get_or_default("benitlux", "")}}}><a href="http://xymus.net/benitlux/">Benitlux</a></li>
72 </ul>
73
74 <ul class="nav navbar-nav pull-right">
75 """
76 if login_placeholder then add "%header_right%"
77
78 add """
79 </ul>
80 </div>
81 </div>
82 </nav>"""
83 end
84
85 redef fun to_s do return write_to_string
86 end
87
88 class OpportunityMasterHeader
89 super OpportunityHeader
90
91 var master_header: MasterHeader
92
93 redef fun rendering
94 do
95 add """
96 <!DOCTYPE html>
97 <html>
98 <head>
99 <title>Opportunity - The meetup planner</title>
100 <meta charset="utf-8">
101 <meta name="viewport" content="width=device-width, initial-scale=1">
102 <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
103 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
104 <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
105 <script>
106 {{{tracking_code}}}
107 {{{page_js}}}
108 </script>
109 <style>
110 .answer:hover {
111 cursor:pointer;
112 }
113 .opportunity-action:hover {
114 cursor:pointer;
115 }
116 </style>
117 </head>
118 <body>"""
119 add master_header
120 end
121 end
122
123 redef class TnitterWeb
124 redef var header = (new MasterHeader("tnitter", true)).to_s
125
126 redef fun javascript_header do return tracking_code
127 end
128
129 redef class BenitluxDocument
130 redef var header = new MasterHeader("benitlux", false)
131 end
132
133 redef class ErrorTemplate
134 redef var header = new MasterHeader(null, false)
135 end
136
137 redef class OpportunityPage
138 redef var header = new OpportunityMasterHeader(new MasterHeader("opportunity", false))
139 end
140
141 redef class FileServer
142
143 redef fun javascript_header do return tracking_code
144 end
145
146 redef class MeetupCreationPage
147 redef var templates do
148 var map = super
149 map["Pizzas spécial LATECE"] = ["Végétarienne", "Pepperoni", "Viandes", "Poulet BBQ"]
150 map["Heures de réunion à l'UQAM"] = ["7h 30", "9h", "10h 30", "12h",
151 "13h 30", "15h", "16h 30", "18h"]
152 return map
153 end
154 end
155
156 fun tracking_code: String do return """
157 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
158 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
159 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
160 })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
161
162 ga('create', 'UA-574578-1', 'auto');
163 ga('send', 'pageview');
164 """
165
166 # Avoid executing when running tests
167 if "NIT_TESTING".environ == "true" then exit 0
168
169 # Setup server interfaces
170 #
171 # Change these to use this config on your own server!
172 var default_vh = new VirtualHost("xymus.net:80")
173 var vps_vh = new VirtualHost("vps.xymus.net:80")
174 var tnitter_vh = new VirtualHost("tnitter.xymus.net:80")
175 var pep8_vh = new VirtualHost("pep8.xymus.net:80")
176 var benitlux_vh = new VirtualHost("benitlux.xymus.net:80")
177 var benitlux_admin_vh = new VirtualHost("localhost:8081")
178
179 var factory = new HttpFactory.and_libevent
180 factory.config.virtual_hosts.add default_vh
181 factory.config.virtual_hosts.add vps_vh
182 factory.config.virtual_hosts.add tnitter_vh
183 factory.config.virtual_hosts.add pep8_vh
184 factory.config.virtual_hosts.add benitlux_vh
185 factory.config.virtual_hosts.add benitlux_admin_vh
186
187 # Ports are open, drop to a low-privileged user if we are root
188 var user_group = new UserGroup("nitcorn", "nitcorn")
189 if sys.uid == 0 then user_group.drop_privileges
190
191 # Files shared by all the virtual hosts (mostly for the common header)
192 var shared_file_server = new FileServer("/var/www/static/")
193
194 # Tnitter is available at `tnitter.xymus.net` and `xymus.net/tnitter/`
195 var tnitter = new TnitterWeb
196 default_vh.routes.add new Route("/tnitter", tnitter)
197
198 tnitter_vh.routes.add new Route("/rest/", new TnitterREST)
199 tnitter_vh.routes.add new Route("/push/", new TnitterPush)
200 tnitter_vh.routes.add new Route("/static/", shared_file_server)
201 tnitter_vh.routes.add new Route(null, tnitter)
202
203 # Pep/8 Analysis is only a file server. It is available at `pep8.xymus.net`
204 # and through the global/default file server at `xymus.net/pep8/`
205 #
206 # TODO Implement pep8analysis server-side with a nitcorn action
207 pep8_vh.routes.add new Route("/static/", shared_file_server)
208 pep8_vh.routes.add new Route(null, new FileServer("/var/www/pep8/"))
209
210 # Benitlux is available at `benitlux.xymus.net` and `xymus.net/benitlux/`
211 #
212 # It has 2 actions/Web interfaces. The Web user UI to subscribe and unsubscribe
213 # to the mailing list. And the RESTful interface used by the Android app.
214
215 var db_path = "benitlux_sherbrooke.db"
216 var benitlux_db = new BenitluxDB.open(db_path)
217 var db_error = benitlux_db.error
218 if db_error != null then
219 print_error db_error
220 exit 1
221 end
222
223 var benitlux_sub = new BenitluxSubscriptionAction(benitlux_db)
224 var benitlux_rest = new BenitluxRESTAction(benitlux_db)
225 var benitlux_push = new BenitluxPushAction(benitlux_db)
226 default_vh.routes.add new Route("/benitlux/rest/", benitlux_rest)
227 default_vh.routes.add new Route("/benitlux/push/", benitlux_push)
228 default_vh.routes.add new Route("/benitlux", benitlux_sub)
229 benitlux_vh.routes.add new Route("/rest/", benitlux_rest)
230 benitlux_vh.routes.add new Route("/push/", benitlux_push)
231 benitlux_vh.routes.add new Route("/static/", shared_file_server)
232 benitlux_vh.routes.add new Route(null, benitlux_sub)
233
234 benitlux_admin_vh.routes.add new Route(null, new BenitluxAdminAction(benitlux_db))
235
236 # Opportunity service
237 var opportunity = new OpportunityWelcome
238 var opportunity_rest = new OpportunityRESTAction
239 default_vh.routes.add new Route("/opportunity/rest/", opportunity_rest)
240 default_vh.routes.add new Route("/opportunity", opportunity)
241
242 # Nitiwiki modification form
243 var passwords = "nitiwiki_passwords".to_path.read_lines
244 assert passwords.not_empty
245 default_vh.routes.add new Route("/edit", new EditAction("http://xymus.net/", "/home/xymus/projects/wiki/config.ini", passwords))
246
247 # We use a special file server for the path `xymus.net/ens` only to display
248 # a different header.
249 var file_server_ens = new FileServer("/var/www/ens/")
250 file_server_ens.header = (new MasterHeader("ens", false))
251 default_vh.routes.add new Route("/ens", file_server_ens)
252
253 # Default file server is used for the main page at `xymus.net` and it is
254 # the default action for any path not caught by other actions.
255 var file_server = new FileServer("/var/www/")
256 file_server.header = (new MasterHeader(null, false))
257 default_vh.routes.add new Route(null, file_server)
258 vps_vh.routes.add new Route(null, file_server)
259
260 # Launch server main loop
261 factory.run