Created
February 8, 2011 03:37
-
-
Save hdenk/815806 to your computer and use it in GitHub Desktop.
clojure webapp with http-authentication using ring/moustache, deployable as foo.war
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gradle-build that uses meikel brandmeyers clojure-plugin for gradle (clojuresque) | |
// see http://bitbucket.org/kotarak/clojuresque | |
// use a standard maven directory-layout -> /src/main/clojure, /src/main/webapp | |
apply plugin: 'clojure' | |
apply plugin: 'war' | |
apply plugin: 'project-report' | |
warnOnReflection = false | |
aotCompile = true // needed for gen-class in servlet.clj | |
repositories { | |
clojureReleasesRepo() // <- clojure-system | |
clojarsRepo() // <- ring, moustache | |
mavenCentral() // <- jetty et al. | |
} | |
dependencies { | |
compile 'org.clojure:clojure:1.2.0' | |
compile 'org.clojure:clojure-contrib:1.2.0' | |
compile 'ring:ring:0.3.5' | |
// workaround gradle-issue 1303 using client-module | |
compile module('net.cgrand:moustache:1.0.0') { | |
dependency 'org.clojure:clojure:1.2.0' | |
//dependency 'ring:ring-core:0.3.5' | |
} | |
providedCompile 'javax.servlet:servlet-api:2.5@jar' | |
providedCompile 'ring:ring-jetty-adapter:0.3.5@jar' | |
providedRuntime 'org.mortbay.jetty:jetty:6.1.14@jar' | |
providedRuntime 'org.mortbay.jetty:jetty-util:6.1.14@jar' | |
} | |
task explodedWar(type: Copy) { | |
from war.rootSpec // reuses the declaration from the war task | |
into new File(buildDir, 'exploded-war') | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns webapp.core | |
(:use | |
net.cgrand.moustache | |
ring.util.response | |
[ring.middleware file params session] | |
ring.adapter.jetty)) | |
; http://localhost:8080/foo -> home | |
; http://localhost:8080/foo/bar -> home (err=not-logged-in) | |
; http://localhost:8080/foo/login?user=doe&password=test -> bar: doe | |
; http://localhost:8080/foo/admin -> home (err=not-admin) | |
; http://localhost:8080/foo/login?user=admin&password=secret -> bar: admin | |
; http://localhost:8080/foo/admin -> admin | |
; http://localhost:8080/foo/logout -> home | |
(defn authenticate-user | |
[{params :params}] | |
(let [user (params "user") password (params "password")] | |
(if (or (and (= user "doe") (= password "test")) | |
(and (= user "admin") (= password "secret"))) | |
(assoc (redirect "/foo/bar") :session {:user user}) | |
(redirect "/foo?err=login-error")))) | |
(defn authenticated? | |
[session] | |
(seq (:user session))) | |
(defn admin-user? | |
[session] | |
(= "admin" (:user session))) | |
(defn wrap-user-security | |
[app] | |
(fn [req] | |
(let [uri (:uri req) session (:session req)] | |
(if (or (authenticated? session) | |
(.startsWith uri "/css/") ; *.css | |
(.startsWith uri "/scripts/")) ; *.js | |
(app req) | |
(redirect "/foo?err=not-logged-in"))))) | |
(defn wrap-admin-security | |
[app] | |
(fn [req] | |
(let [session (:session req)] | |
(if (admin-user? session) | |
(app req) | |
(redirect "/foo?err=not-admin"))))) | |
(defn logout | |
[req] | |
(assoc (redirect "/foo") | |
:session nil)) | |
(defn page-not-found [_] | |
{:status 404 :headers {"Content-Type" "text/html"} | |
:body "<html><body><p>page not found</p></body></html>"}) | |
(defn home_handler [req] | |
(response "<html><body><p>home</p></body></html>")) | |
(defn bar_handler [req] | |
(response (str "<html><body><p>bar: " (-> req :session :user) "</p></body></html>"))) | |
(defn admin_handler [req] | |
(response "<html><body><p>admin</p></body></html>")) | |
; using composition, url-mapping und access-control | |
; can be implemented in a quite elegant way | |
(def routes | |
(app | |
(wrap-session) | |
["foo"] home_handler | |
["foo" "login"] (wrap-params authenticate-user) | |
["foo" &] (app | |
(wrap-user-security) | |
; switch wrap-file before building the war ! | |
;(wrap-file "/path-to-your-webapps-dir/webapps/foo") | |
(wrap-file "src/main/webapp") | |
["bar"] bar_handler | |
["logout"] logout | |
["admin" &] (app | |
(wrap-admin-security) | |
[""] admin_handler | |
[&] pass) | |
[&] pass) | |
[&] page-not-found)) | |
; comment the following line and switch (wrap-file *) | |
; before building the war with cmd: gradle clean war | |
(doto (Thread. #(run-jetty #'routes {:port 8080})) .start) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns webapp.servlet | |
(:use [ring.util.servlet :only (defservice)]) | |
(:use [ring.middleware.stacktrace :only (wrap-stacktrace)]) | |
(:use [webapp.core :only (routes)]) | |
(:gen-class :extends javax.servlet.http.HttpServlet)) | |
(def app | |
(-> #'routes | |
(wrap-stacktrace))) | |
(defservice app) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<web-app> | |
<display-name>foo</display-name> | |
<servlet> | |
<servlet-name>foo</servlet-name> | |
<servlet-class>webapp.servlet</servlet-class> | |
</servlet> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.css</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.csv</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.gif</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.ico</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.jpg</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.png</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>default</servlet-name> | |
<url-pattern>*.js</url-pattern> | |
</servlet-mapping> | |
<servlet-mapping> | |
<servlet-name>foo</servlet-name> | |
<url-pattern>/*</url-pattern> | |
</servlet-mapping> | |
</web-app> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Links