Skip to content

Commit 5fe8772

Browse files
committed
Fixed jaliss#431: Added SecureSocial.currentUser to support Websockets
1 parent f0a7129 commit 5fe8772

File tree

7 files changed

+115
-8
lines changed

7 files changed

+115
-8
lines changed

ChangeLog

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
master -
2+
- Added SecureSocial.currentUser to support Websockets
23
- Fixed #429: null pointer exception in UserAware Java API (thanks @mangecoeur)
34
- Pull request #159: Weibo support (thanks @qiuzhanghua and @wuhaixing)
45
- Pull request #398: Dropbox support (thanks @deterdw)

module-code/app/securesocial/core/SecureSocial.scala

+17
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,21 @@ object SecureSocial {
213213
import play.api.Play
214214
Play.current.configuration.getBoolean("securesocial.enableRefererAsOriginalUrl").getOrElse(false)
215215
}
216+
217+
/**
218+
* Returns the current user. Invoke this only if you are executing code
219+
* without a SecuredRequest or UserAwareRequest available. For most cases what SecuredAction or UserAwareAction
220+
* gives you will be enough.
221+
*
222+
* @param request the current request
223+
* @param env the current environment
224+
* @tparam U the user type
225+
* @return a future with an option user
226+
*/
227+
def currentUser[U](implicit request: RequestHeader, env: RuntimeEnvironment[U], ec: ExecutionContext): Future[Option[U]] = {
228+
env.authenticatorService.fromRequest.map {
229+
case Some(authenticator) if authenticator.isValid => Some(authenticator.user)
230+
case _ => None
231+
}
232+
}
216233
}

module-code/app/securesocial/core/java/SecureSocial.java

+44
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
*/
1717
package securesocial.core.java;
1818

19+
import play.api.mvc.RequestHeader;
20+
import play.libs.F;
21+
import play.libs.HttpExecution;
1922
import play.mvc.Http;
23+
import scala.Option;
24+
import scala.concurrent.ExecutionContext;
2025
import securesocial.core.RuntimeEnvironment;
26+
import securesocial.core.SecureSocial$;
2127

2228
/**
2329
*
@@ -39,4 +45,42 @@ public class SecureSocial {
3945
public static RuntimeEnvironment env() {
4046
return (RuntimeEnvironment) Http.Context.current().args.get("securesocial-env");
4147
}
48+
49+
/**
50+
* Returns the current user. Invoke this only if you are executing code
51+
* without a SecuredAction or UserAware action available (eg: using WebSockets). For other cases this
52+
* should not be needed.
53+
*
54+
* @param env the environment
55+
* @return the current user object or null if there isn't one available
56+
*/
57+
public static F.Promise<Object> currentUser(RuntimeEnvironment env) {
58+
return currentUser(env, HttpExecution.defaultContext());
59+
}
60+
61+
/**
62+
* Returns the current user. Invoke this only if you are executing code
63+
* without a SecuredAction or UserAware action available (eg: using WebSockets). For other cases this
64+
* should not be needed.
65+
*
66+
* @param env the environment
67+
* @param executor an ExecutionContext
68+
* @return the current user object or null if there isn't one available
69+
*/
70+
public static F.Promise<Object> currentUser(RuntimeEnvironment env, ExecutionContext executor) {
71+
RequestHeader requestHeader = Http.Context.current()._requestHeader();
72+
if (requestHeader == null || env == null) {
73+
return F.Promise.promise(null);
74+
} else {
75+
scala.concurrent.Future scalaFuture = SecureSocial$.MODULE$.currentUser(requestHeader, env, executor);
76+
F.Function<Option<Object>, Object> mapFunction = new F.Function<Option<Object>, Object>() {
77+
78+
@Override
79+
public Object apply(Option<Object> objectOption) throws Throwable {
80+
return objectOption.isDefined() ? objectOption.get() : null;
81+
}
82+
};
83+
return F.Promise.wrap(scalaFuture).map(mapFunction);
84+
}
85+
}
4286
}

samples/java/demo/app/controllers/Application.java

+33
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package controllers;
1818

1919
import play.Logger;
20+
import play.libs.F;
2021
import play.mvc.Controller;
2122
import play.mvc.Result;
2223
import securesocial.core.BasicProfile;
24+
import securesocial.core.RuntimeEnvironment;
2325
import securesocial.core.java.SecureSocial;
2426
import securesocial.core.java.SecuredAction;
2527
import securesocial.core.java.UserAwareAction;
@@ -33,6 +35,17 @@
3335
*/
3436
public class Application extends Controller {
3537
public static Logger.ALogger logger = Logger.of("application.controllers.Application");
38+
private RuntimeEnvironment env;
39+
40+
/**
41+
* A constructor needed to get a hold of the environment instance.
42+
* This could be injected using a DI framework instead too.
43+
*
44+
* @param env
45+
*/
46+
public Application(RuntimeEnvironment env) {
47+
this.env = env;
48+
}
3649
/**
3750
* This action only gets called if the user is logged in.
3851
*
@@ -77,4 +90,24 @@ public Result linkResult() {
7790
DemoUser current = (DemoUser) ctx().args.get(SecureSocial.USER_KEY);
7891
return ok(linkResult.render(current, current.identities));
7992
}
93+
94+
/**
95+
* Sample use of SecureSocial.currentUser. Access the /current-user to test it
96+
*/
97+
public F.Promise<Result> currentUser() {
98+
return SecureSocial.currentUser(env).map( new F.Function<Object, Result>() {
99+
@Override
100+
public Result apply(Object maybeUser) throws Throwable {
101+
String id;
102+
103+
if ( maybeUser != null ) {
104+
DemoUser user = (DemoUser) maybeUser;
105+
id = user.main.userId();
106+
} else {
107+
id = "not available. Please log in.";
108+
}
109+
return ok("your id is " + id);
110+
}
111+
});
112+
}
80113
}

samples/java/demo/conf/routes

+7-6
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
# ~~~~
44

55
# Home page
6-
GET / @controllers.Application.index
7-
GET /userAware @controllers.Application.userAware
8-
GET /only-twitter @controllers.Application.onlyTwitter
9-
GET /link-result @controllers.Application.linkResult
6+
GET / @controllers.Application.index
7+
GET /userAware @controllers.Application.userAware
8+
GET /only-twitter @controllers.Application.onlyTwitter
9+
GET /link-result @controllers.Application.linkResult
10+
GET /current-user @controllers.Application.currentUser
1011

1112
# Map static resources from the /public folder to the /assets URL path
12-
GET /assets/*file controllers.Assets.at(path="/public", file)
13-
-> /auth securesocial.Routes
13+
GET /assets/*file controllers.Assets.at(path="/public", file)
14+
-> /auth securesocial.Routes

samples/scala/demo/app/controllers/Application.scala

+12-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package controllers
1818

1919
import securesocial.core._
2020
import service.DemoUser
21-
import play.api.mvc.RequestHeader
21+
import play.api.mvc.{Action, RequestHeader}
2222

2323
class Application(override implicit val env: RuntimeEnvironment[DemoUser]) extends securesocial.core.SecureSocial[DemoUser] {
2424
def index = SecuredAction { implicit request =>
@@ -33,6 +33,17 @@ class Application(override implicit val env: RuntimeEnvironment[DemoUser]) exten
3333
def linkResult = SecuredAction { implicit request =>
3434
Ok(views.html.linkResult(request.user))
3535
}
36+
37+
/**
38+
* Sample use of SecureSocial.currentUser. Access the /current-user to test it
39+
*/
40+
def currentUser = Action.async { implicit request =>
41+
import play.api.libs.concurrent.Execution.Implicits._
42+
SecureSocial.currentUser[DemoUser].map { maybeUser =>
43+
val userId = maybeUser.map(_.main.userId).getOrElse("unknown")
44+
Ok(s"Your id is $userId")
45+
}
46+
}
3647
}
3748

3849
// An Authorization implementation that only authorizes uses that logged in using twitter

samples/scala/demo/conf/routes

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
GET / @controllers.Application.index
77
GET /only-twitter @controllers.Application.onlyTwitter
88
GET /link-result @controllers.Application.linkResult
9-
9+
GET /current-user @controllers.Application.currentUser
1010
GET /custom/login @controllers.CustomLoginController.login
1111
GET /custom/logout @controllers.CustomLoginController.logout
1212

0 commit comments

Comments
 (0)