# Runs a webserver based on nitcorn that render things from model.
module nitweb
+import popcorn::pop_config
+import popcorn::pop_auth
import frontend
import web
+redef class NitwebConfig
+
+ # Github client id used for Github OAuth login.
+ #
+ # * key: `github.client_id`
+ # * default: ``
+ var github_client_id: String is lazy do return value_or_default("github.client.id", "")
+
+ # Github client secret used for Github OAuth login.
+ #
+ # * key: `github.client_secret`
+ # * default: ``
+ var github_client_secret: String is lazy do
+ return value_or_default("github.client.secret", "")
+ end
+end
+
redef class ToolContext
- # Host name to bind on.
+ # Path to app config file.
+ var opt_config = new OptionString("Path to app config file", "--config")
+
+ # Host name to bind on (will overwrite the config one).
var opt_host = new OptionString("Host to bind the server on", "--host")
- # Port number to bind on.
- var opt_port = new OptionInt("Port number to use", 3000, "--port")
+ # Port number to bind on (will overwrite the config one).
+ var opt_port = new OptionInt("Port number to use", -1, "--port")
# Web rendering phase.
var webphase: Phase = new NitwebPhase(self, null)
init do
super
- option_context.add_option(opt_host, opt_port)
+ option_context.add_option(opt_config, opt_host, opt_port)
end
end
# Phase that builds the model and wait for http request to serve pages.
private class NitwebPhase
super Phase
+
+ # Build the nitweb config from `toolcontext` options.
+ fun build_config(toolcontext: ToolContext, mainmodule: MModule): NitwebConfig do
+ var config_file = toolcontext.opt_config.value
+ if config_file == null then config_file = "nitweb.ini"
+ var config = new NitwebConfig(
+ config_file,
+ toolcontext.modelbuilder.model,
+ mainmodule,
+ toolcontext.modelbuilder)
+ var opt_host = toolcontext.opt_host.value
+ if opt_host != null then config["app.host"] = opt_host
+ var opt_port = toolcontext.opt_port.value
+ if opt_port >= 0 then config["app.port"] = opt_port.to_s
+ return config
+ end
+
redef fun process_mainmodule(mainmodule, mmodules)
do
- var model = mainmodule.model
- var modelbuilder = toolcontext.modelbuilder
-
- # Build catalog
- var catalog = new Catalog(modelbuilder)
- for mpackage in model.mpackages do
- catalog.deps.add_node(mpackage)
- for mgroup in mpackage.mgroups do
- for mmodule in mgroup.mmodules do
- for imported in mmodule.in_importation.direct_greaters do
- var ip = imported.mpackage
- if ip == null or ip == mpackage then continue
- catalog.deps.add_edge(mpackage, ip)
- end
- end
- end
- catalog.git_info(mpackage)
- catalog.package_page(mpackage)
- end
-
- # Prepare mongo connection
- var mongo = new MongoClient("mongodb://localhost:27017/")
- var db = mongo.database("nitweb")
- var collection = db.collection("stars")
-
- # Run the server
- var host = toolcontext.opt_host.value or else "localhost"
- var port = toolcontext.opt_port.value
+ var config = build_config(toolcontext, mainmodule)
var app = new App
+ app.use_before("/*", new SessionInit)
app.use_before("/*", new RequestClock)
- app.use("/api", new APIRouter(model, modelbuilder, mainmodule, catalog, collection))
+ app.use("/api", new APIRouter(config))
+ app.use("/login", new GithubLogin(config.github_client_id))
+ app.use("/oauth", new GithubOAuthCallBack(config.github_client_id, config.github_client_secret))
+ app.use("/logout", new GithubLogout)
app.use("/*", new StaticHandler(toolcontext.share_dir / "nitweb", "index.html"))
app.use_after("/*", new ConsoleLog)
- app.listen(host, port.to_i)
- end
-end
-
-# Group all api handlers in one router.
-class APIRouter
- super Router
-
- # Model to pass to handlers.
- var model: Model
-
- # ModelBuilder to pass to handlers.
- var modelbuilder: ModelBuilder
-
- # Mainmodule to pass to handlers.
- var mainmodule: MModule
-
- # Catalog to pass to handlers.
- var catalog: Catalog
-
- # Mongo collection used to store ratings.
- var collection: MongoCollection
-
- init do
- use("/catalog", new APICatalogRouter(model, mainmodule, catalog))
- use("/list", new APIList(model, mainmodule))
- use("/search", new APISearch(model, mainmodule))
- use("/random", new APIRandom(model, mainmodule))
- use("/entity/:id", new APIEntity(model, mainmodule))
- use("/code/:id", new APIEntityCode(model, mainmodule, modelbuilder))
- use("/uml/:id", new APIEntityUML(model, mainmodule))
- use("/linearization/:id", new APIEntityLinearization(model, mainmodule))
- use("/defs/:id", new APIEntityDefs(model, mainmodule))
- use("/feedback/", new APIFeedbackRouter(model, mainmodule, collection))
- use("/inheritance/:id", new APIEntityInheritance(model, mainmodule))
- use("/graph/", new APIGraphRouter(model, mainmodule))
- use("/docdown/", new APIDocdown(model, mainmodule, modelbuilder))
+ app.listen(config.app_host, config.app_port)
end
end
var toolcontext = new ToolContext
var tpl = new Template
tpl.add "Usage: nitweb [OPTION]... <file.nit>...\n"
-tpl.add "Run a webserver based on nitcorn that serve pages about model."
+tpl.add "Run a webserver based on nitcorn that serves pages about model."
toolcontext.tooldescription = tpl.write_to_string
# process options