PageRenderTime 57ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/extra/connect/Global/connect.js

http://antville.googlecode.com/
JavaScript | 334 lines | 267 code | 35 blank | 32 comment | 47 complexity | 5d7c7d067ff181cbe41fbb63e32c9571 MD5 | raw file
  1. // The Antville Project
  2. // http://code.google.com/p/antville
  3. //
  4. // Copyright 2007-2011 by Tobi Schäfer.
  5. //
  6. // Copyright 2001–2007 Robert Gaggl, Hannes Wallnöfer, Tobi Schäfer,
  7. // Matthias & Michael Platzer, Christoph Lincke.
  8. //
  9. // Licensed under the Apache License, Version 2.0 (the ``License'');
  10. // you may not use this file except in compliance with the License.
  11. // You may obtain a copy of the License at
  12. //
  13. // http://www.apache.org/licenses/LICENSE-2.0
  14. //
  15. // Unless required by applicable law or agreed to in writing, software
  16. // distributed under the License is distributed on an ``AS IS'' BASIS,
  17. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. // See the License for the specific language governing permissions and
  19. // limitations under the License.
  20. //
  21. // $Revision: 4598 $
  22. // $Author: interface@p3k.org $
  23. // $Date: 2013-07-23 22:10:05 +0200 (Tue, 23 Jul 2013) $
  24. // $URL: http://antville.googlecode.com/svn/trunk/extra/connect/Global/connect.js $
  25. /**
  26. * @fileoverview Defines the Antville Connect Feature.
  27. */
  28. app.addRepository(app.dir + "/../extra/connect/scribe-1.3.0.jar");
  29. // FIXME: Connecting with Twitter and Google currently does not return an e-mail address.
  30. // Instead, noreplay@antville.org is used – which is very poor and should be fixed ASAP.
  31. // FIXME: Might be good to somehow define the action together with its permissions...
  32. Members.prototype.connect_action = function() {
  33. try {
  34. var connect = Feature.get("connect");
  35. switch (req.data.type) {
  36. case "facebook":
  37. connect.facebook(req);
  38. break;
  39. case "google":
  40. connect.google(req);
  41. break;
  42. case "twitter":
  43. connect.scribe(req.data.type);
  44. break;
  45. }
  46. } catch (ex) {
  47. session.logout();
  48. res.message = String(ex);
  49. res.redirect(res.handlers.members.href("login"));
  50. }
  51. JSON.sendPaddedResponse(this._parent.stories.getPermission("create"));
  52. res.redirect(User.getLocation() || res.handlers.site.href());
  53. return;
  54. }
  55. Members.prototype.disconnect_action = function() {
  56. switch (req.data.type) {
  57. case "facebook":
  58. case "google":
  59. case "twitter":
  60. res.handlers.membership.creator.deleteMetadata(req.data.type + "_id");
  61. break;
  62. }
  63. res.redirect(req.data.http_referer);
  64. return;
  65. }
  66. Feature.add("connect", "http://code.google.com/p/antville/wiki/ConnectFeature", {
  67. _getPermission: function(action) {
  68. if (this.constructor === Members) {
  69. switch (action) {
  70. case "connect":
  71. return true;
  72. case "disconnect":
  73. return User.require(User.REGULAR);
  74. }
  75. }
  76. },
  77. main: function(options) {
  78. var defaultDomain = getProperty("domain.*");
  79. var domain = getProperty("domain." + res.handlers.site.name);
  80. if (defaultDomain && domain && !domain.endsWith(defaultDomain)) {
  81. return;
  82. }
  83. var suffix = options.context ? "_" + options.context : "";
  84. getProperty("connect.facebook.id") && renderSkin("connect#facebook" + suffix);
  85. getProperty("connect.google.id") && renderSkin("connect#google" + suffix);
  86. getProperty("connect.twitter.id") && renderSkin("connect#twitter" + suffix);
  87. },
  88. getUserByConnection: function(type, id) {
  89. var user;
  90. var connections = root.connections.get(id);
  91. if (connections) {
  92. connections.forEach(function(index) {
  93. if (this.name === type + "_id") {
  94. user = this.parent;
  95. }
  96. });
  97. }
  98. return user;
  99. },
  100. scribe: function(type) {
  101. var name = type.titleize();
  102. var appId = getProperty("connect." + type + ".id");
  103. var secret = getProperty("connect." + type + ".key");
  104. if (!secret || req.data.denied) {
  105. throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name,
  106. gettext("You denied the request.")));
  107. }
  108. if (req.isPost()) {
  109. try {
  110. User.login(req.postParams);
  111. } catch (ex) { }
  112. }
  113. var scribe = Packages.org.scribe;
  114. var provider, requestUrl, scope, getValues;
  115. var headers = {};
  116. switch (type) {
  117. case "google":
  118. provider = scribe.builder.api.GoogleApi;
  119. requestUrl = "http://www-opensocial.googleusercontent.com/api/people/@me/@self";
  120. scope = "http://www-opensocial.googleusercontent.com/api/people/";
  121. headers["GData-Version"] = "3.0";
  122. getValues = function(data) {
  123. data = data.entry;
  124. return {
  125. id: data.id,
  126. name: data.displayName,
  127. email: data.email,
  128. url: data.url
  129. }
  130. }
  131. break;
  132. case "twitter":
  133. provider = scribe.builder.api.TwitterApi;
  134. requestUrl = "https://api.twitter.com/1.1/account/verify_credentials.json";
  135. getValues = function(data) {
  136. return {
  137. id: data.id_str,
  138. name: data.screen_name,
  139. email: data.email,
  140. url: data.profileUrl
  141. }
  142. }
  143. break;
  144. }
  145. var url = res.handlers.members.href(req.action) + "?type=" + type;
  146. var service = new scribe.builder.ServiceBuilder()
  147. .provider(provider)
  148. .apiKey(appId)
  149. .apiSecret(secret)
  150. .callback(url);
  151. if (scope) {
  152. service.scope(scope);
  153. }
  154. var oauth = service.build();
  155. var verifier = req.data.oauth_verifier;
  156. if (!verifier) {
  157. // Because the service provider will redirect back to this URL the
  158. // request token needs to be stored in the session object
  159. session.data.requestToken = oauth.getRequestToken();
  160. res.redirect(oauth.getAuthorizationUrl(session.data.requestToken));
  161. }
  162. try {
  163. var accessToken = oauth.getAccessToken(session.data.requestToken,
  164. new scribe.model.Verifier(verifier));
  165. } catch (ex) {
  166. throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name,
  167. gettext("Something went wrong.")));
  168. }
  169. var request = new scribe.model.OAuthRequest(scribe.model.Verb.GET, requestUrl);
  170. oauth.signRequest(accessToken, request);
  171. for (let name in headers) {
  172. request.addHeader(name, headers[name]);
  173. }
  174. var response = request.send();
  175. var data = getValues(JSON.parse(response.getBody()));
  176. var user = this.getUserByConnection(type, data.id);
  177. if (!user) {
  178. if (!session.user) {
  179. var name = root.users.getAccessName(data.name);
  180. user = User.register({
  181. name: name,
  182. hash: session.data.requestToken.getToken(),
  183. email: data.email || root.replyTo,
  184. url: data.url
  185. });
  186. session.login(user);
  187. } else {
  188. user = session.user;
  189. }
  190. user.setMetadata(type + "_id", data.id);
  191. } else if (user !== session.user) {
  192. user.touch();
  193. session.login(user);
  194. }
  195. return;
  196. },
  197. facebook: function(req) {
  198. var appId = getProperty("connect.facebook.id");
  199. var secret = getProperty("connect.facebook.key");
  200. if (!secret || req.data.error) {
  201. throw Error(gettext("Could not connect with Facebook. ({0})", -1));
  202. }
  203. if (req.isPost()) {
  204. try {
  205. User.login(req.postParams);
  206. } catch (ex) { }
  207. }
  208. var url = res.handlers.members.href(req.action) + "?type=facebook";
  209. var code = req.data.code;
  210. if (!code) {
  211. res.redirect("https://www.facebook.com/dialog/oauth?client_id=" + appId +
  212. "&scope=email&redirect_uri=" + url);
  213. return;
  214. }
  215. var mime = getURL("https://graph.facebook.com/oauth/access_token?client_id=" + appId +
  216. "&redirect_uri=" + url + "&client_secret=" + secret + "&code=" + code);
  217. if (!mime || !mime.text) {
  218. throw Error(gettext("Could not connect with Facebook. ({0})", -3));
  219. }
  220. var token = mime.text;
  221. mime = getURL("https://graph.facebook.com/me?" + token);
  222. if (!mime) {
  223. throw Error(gettext("Could not connect with Facebook. ({0})", -4));
  224. }
  225. var content = Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream);
  226. if (!content) {
  227. throw Error(gettext("Could not connect with Facebook. ({0})", -5));
  228. }
  229. var data = JSON.parse(content);
  230. var user = this.getUserByConnection("facebook", data.id);
  231. if (!user) {
  232. if (!session.user) {
  233. var name = root.users.getAccessName(data.name);
  234. user = User.register({
  235. name: name,
  236. hash: token,
  237. email: data.email,
  238. url: data.link,
  239. });
  240. session.login(user);
  241. } else {
  242. user = session.user;
  243. }
  244. user.setMetadata("facebook_id", data.id);
  245. } else if (user !== session.user) {
  246. user.touch();
  247. session.login(user);
  248. }
  249. return;
  250. },
  251. google: function(req) {
  252. if (req.isPost()) {
  253. try {
  254. User.login(req.postParams);
  255. } catch (ex) { }
  256. }
  257. var url = root.members.href('connect') + "?type=google";
  258. if (req.data.code) {
  259. var http = new helma.Http();
  260. http.setMethod("POST");
  261. http.setContent("code=" + encodeURIComponent(req.data.code) +
  262. "&client_id=" + encodeURIComponent(getProperty("connect.google.id")) +
  263. "&client_secret=" + encodeURIComponent(getProperty("connect.google.key")) +
  264. "&redirect_uri=" + encodeURIComponent(url) + "&grant_type=authorization_code");
  265. var response = http.getUrl("https://accounts.google.com/o/oauth2/token");
  266. var data = JSON.parse(response.content);
  267. var token = data.access_token;
  268. var mime = getURL("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" +
  269. encodeURIComponent(data.access_token));
  270. var data = JSON.parse(Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream));
  271. var user = this.getUserByConnection("google", data.id);
  272. if (!user) {
  273. if (!session.user) {
  274. var name = root.users.getAccessName(data.name);
  275. user = User.register({
  276. name: name,
  277. hash: token,
  278. email: data.email,
  279. url: data.link
  280. });
  281. session.login(user);
  282. } else {
  283. user = session.user;
  284. }
  285. user.setMetadata("google_id", data.id);
  286. } else if (user !== session.user) {
  287. user.touch();
  288. session.login(user);
  289. }
  290. } else {
  291. res.redirect("https://accounts.google.com/o/oauth2/auth?" +
  292. "client_id=" + encodeURIComponent(getProperty("connect.google.id")) +
  293. "&redirect_uri=" + encodeURIComponent(url) +
  294. "&scope=" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.profile") +
  295. "+" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.email") +
  296. "&response_type=code");
  297. }
  298. }
  299. });