contrib/benitlux: intro the admin server interface with daily notification
authorAlexis Laferrière <alexis.laf@xymus.net>
Tue, 5 Apr 2016 20:29:28 +0000 (16:29 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Mon, 16 May 2016 21:27:12 +0000 (17:27 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

contrib/benitlux/src/benitlux_controller.nit
contrib/benitlux/src/benitlux_model.nit
contrib/benitlux/src/benitlux_web.nit

index 5f5513a..c65ac37 100644 (file)
@@ -322,6 +322,57 @@ redef class Sys
 end
 
 # ---
+# Administration
+
+# Path to the secret used to authenticate admin requests
+fun secret_path: String do return "benitlux.secret"
+
+# Services reserved to administrators
+class BenitluxAdminAction
+       super BenitluxAction
+       super RestfulAction
+
+       private fun server_secret: String do return secret_path.to_path.read_all
+
+       # Trigger sending daily menu to connected clients
+       #
+       # This should usually be called by an external cron program.
+       # send_daily_updates?secret=shared_secret -> true | BenitluxError
+       fun send_daily_updates(secret: nullable String): HttpResponse
+       is restful do
+               # Check secrets
+               var server_secret = server_secret
+               if server_secret.is_empty then
+                       print_error "The admin interface needs a secret at '{secret_path}'"
+                       return new HttpResponse.server_error
+               end
+
+               if server_secret != secret then
+                       return new HttpResponse.invalid_token
+               end
+
+               # Load beer menu
+               var list = db.list_beers_and_rating
+               if list == null then return new HttpResponse.server_error
+
+               var msg = new DailyNotification(list)
+
+               # Broadcast updates
+               for conn in push_connections.values.to_a do
+                       if not conn.closed then
+                               conn.respond new HttpResponse.ok(msg)
+                               conn.close
+                       end
+               end
+               push_connections.clear
+
+               return new HttpResponse.ok(true)
+       end
+
+       redef fun answer(request, turi) do return new HttpResponse.bad_request
+end
+
+# ---
 # Misc services
 
 redef class Text
index 987047f..48a807a 100644 (file)
@@ -234,6 +234,14 @@ class CheckinReport
        var users = new Array[User]
 end
 
+# Daily menu notifications
+class DailyNotification
+       serialize
+
+       # All beers on the menu today
+       var beers: Array[BeerAndRatings]
+end
+
 # Server or API usage error
 class BenitluxError
        super Error
index d5bab54..3b2743b 100644 (file)
@@ -25,6 +25,9 @@ import benitlux_restful
 # Listening interface
 fun iface: String do return "localhost:8080"
 
+# Listening interface for admin commands
+fun iface_admin: String do return "localhost:8081"
+
 # Sqlite3 database
 var db_path = "benitlux_sherbrooke.db"
 var db = new BenitluxDB.open(db_path)
@@ -40,10 +43,14 @@ vh.routes.add new Route("/rest/", new BenitluxRESTAction(db))
 vh.routes.add new Route("/push/", new BenitluxPushAction(db))
 vh.routes.add new Route(null, new BenitluxSubscriptionAction(db))
 
+var vh_admin = new VirtualHost(iface_admin)
+vh_admin.routes.add new Route(null, new BenitluxAdminAction(db))
+
 var factory = new HttpFactory.and_libevent
 factory.config.virtual_hosts.add vh
+factory.config.virtual_hosts.add vh_admin
 
-print "Launching server on http://{iface}/"
+print "Launching server on http://{iface}/ and http://{iface_admin}/"
 factory.run
 
 db.close