Guest User

Untitled

a guest
Oct 14th, 2018
220
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.94 KB | None | 0 0
  1. var Cloud = require('ti.cloud'),
  2. Ember = require('/lib/em_ti/ember-runtime'),
  3. Keychain = require('com.obscure.keychain'),
  4. User = require('/models/user');
  5.  
  6. /**
  7. @class
  8.  
  9. Manage Appcelerator Cloud Services, Facebook, and Twitter accounts.
  10.  
  11. @extends Ember.Object
  12. */
  13. var UsersController = Ember.Object.extend({
  14. /**
  15. The current logged in user.
  16.  
  17. @property {User}
  18. */
  19. content: User.create(),
  20.  
  21. /**
  22. Array of Users found via Facebook.
  23.  
  24. @property {Array}
  25. */
  26. facebookFriends: [],
  27.  
  28. /**
  29. Array of Users found via Twitter.
  30.  
  31. @property {Array}
  32. */
  33. twitterFriends: [],
  34.  
  35. /**
  36. Initialize the controller with the Facebook and Twitter keys,
  37. and listen for when the user authorizes Facebook or Twitter.
  38. */
  39. init: function() {
  40. this._super();
  41.  
  42. var facebookAppId = Ti.App.Properties.getString('facebook-app-id', null),
  43. twitterConsumerKey = Ti.App.Properties.getString('twitter-consumer-key', null),
  44. twitterConsumerSecret = Ti.App.Properties.getString('twitter-consumer-secret', null),
  45. self = this;
  46.  
  47. if (facebookAppId === null) {
  48. Ti.API.warn('The property `facebook-app-id` must be set in tiapp.xml to log in with Facebook.');
  49. Ti.API.warn('Example: <property name="facebook-app-id" type="string">[YOUR KEY]</property>');
  50. } else {
  51. Ti.Facebook.appid = facebookAppId;
  52. Ti.Facebook.addEventListener('login', function(e) {
  53. if (e.success) {
  54. var user = self.get('content');
  55. user.set('facebookId', Ti.Facebook.uid);
  56. user.set('facebookAccessToken', Ti.Facebook.accessToken);
  57. if (Ember.none(user.get('name')) && !Ember.none(e.data.name)) {
  58. user.set('name', e.data.name);
  59. }
  60. if (Ember.none(user.get('id'))) {
  61. self.signInWithFacebook();
  62. } else {
  63. self.linkFacebookAccount();
  64. }
  65. } else if (e.error) {
  66. self.handleError(e.error);
  67. } else if (e.cancelled) {
  68. Ti.API.debug('Cancelled Facebook login.');
  69. }
  70. });
  71. }
  72.  
  73. if (twitterConsumerKey === null || twitterConsumerSecret === null) {
  74. Ti.API.warn('The properties `twitter-consumer-key` and `twitter-consumer-secret` must be set in tiapp.xml to log in with Twitter.');
  75. Ti.API.warn('Example: <property name="twitter-consumer-key" type="string">[YOUR KEY]</property>');
  76. Ti.API.warn('Example: <property name="twitter-consumer-secret" type="string">[YOUR KEY]</property>');
  77. } else {
  78. var twitter = require('/lib/ti_platform_connect/twitter').Twitter({
  79. consumerKey: twitterConsumerKey,
  80. consumerSecret: twitterConsumerSecret,
  81. accessTokenKey: Ti.App.Properties.getString('twitterAccessTokenKey', ''),
  82. accessTokenSecret: Ti.App.Properties.getString('twitterAccessTokenSecret', '')
  83. });
  84. this.set('twitter', twitter);
  85.  
  86. twitter.addEventListener('login', function(e) {
  87. if (e.success) {
  88. Ti.App.Properties.setString('twitterAccessTokenKey', e.accessTokenKey);
  89. Ti.App.Properties.setString('twitterAccessTokenSecret', e.accessTokenSecret);
  90. var user = self.get('content');
  91. user.set('twitterAccessTokenKey', e.accessTokenKey);
  92. user.set('twitterAccessTokenSecret', e.accessTokenSecret);
  93.  
  94. twitter.request('1/account/verify_credentials.json', {}, {}, 'GET', function(e) {
  95. if (e.success) {
  96. var json = JSON.parse(e.result.text);
  97. user.set('twitterId', json.id);
  98. if (Ember.none(user.get('name')) && !Ember.none(json.name)) {
  99. user.set('name', json.name);
  100. }
  101. if (Ember.none(user.get('id'))) {
  102. self.signInWithTwitter();
  103. } else {
  104. self.linkTwitterAccount();
  105. }
  106. } else {
  107. self.handleError(e);
  108. }
  109. });
  110. } else {
  111. self.handleError(e);
  112. }
  113. });
  114. }
  115. },
  116.  
  117. /**
  118. Authorize using Facebook for logging in to ACS.
  119. */
  120. authorizeFacebook: function() {
  121. var user = this.get('content');
  122. if (Ti.Facebook.getLoggedIn()) {
  123. user.set('facebookId', Ti.Facebook.uid);
  124. user.set('facebookAccessToken', Ti.Facebook.accessToken);
  125. if (Ember.none(user.get('id'))) {
  126. this.signInWithFacebook();
  127. } else {
  128. this.linkFacebookAccount();
  129. }
  130. } else {
  131. Ti.Facebook.authorize();
  132. }
  133. },
  134.  
  135. /**
  136. Authorize using Twitter for logging in to ACS.
  137. */
  138. authorizeTwitter: function() {
  139. var twitter = this.get('twitter');
  140. twitter.authorize();
  141. },
  142.  
  143. /**
  144. Search for other users who have signed in with Facebook.
  145.  
  146. @param {Hash} options
  147. Hash of options including button, and callback.
  148. */
  149. findFacebookFriends: function(options) {
  150. var self = this;
  151.  
  152. Cloud.SocialIntegrations.searchFacebookFriends(function (e) {
  153. if (e.success) {
  154. Ti.API.info('Success!');
  155. Ti.API.info(e.users);
  156. } else {
  157. self.handleError(e);
  158. }
  159. self.handleCallbacks(options);
  160. });
  161. },
  162.  
  163. /**
  164. Search for other users who have signed in with Twitter.
  165.  
  166. @param {Hash} options
  167. Hash of options including button, and callback.
  168. */
  169. findTwitterFriends: function(options) {
  170. var twitter = this.get('twitter'), self = this;
  171. twitter.request('1/friends/ids.json', {}, {}, 'GET', function(e) {
  172. if (e.success) {
  173. var json = JSON.parse(e.result.text), twitterIds = json.ids;
  174.  
  175. // ACS requires that the Twitter IDs are strings for searching users.
  176. for (var i = 0; i < twitterIds.length; i++) {
  177. twitterIds[i] = twitterIds[i] + '';
  178. }
  179.  
  180. // There also needs to be a limit on the number of ids sent.
  181. var page = 1, perPage = 400, start = 0, end = 0, users = [];
  182.  
  183. var getTwitterUsers = function() {
  184. start = (page - 1) * perPage;
  185. end = twitterIds.length;
  186.  
  187. if (twitterIds.length > page * perPage) {
  188. end = page * perPage;
  189. }
  190.  
  191. var searchIds = twitterIds.slice(start, end);
  192.  
  193. Cloud.Users.query({
  194. where: {
  195. 'external_accounts.external_type': 'twitter',
  196. 'external_accounts.external_id': { $in: searchIds }
  197. }
  198. }, function (e) {
  199. if (e.success) {
  200. users = users.concat(e.users);
  201. if (end === twitterIds.length) {
  202. // Last of the ids to search on ACS. Time to grab the user info from twitter.
  203. var twitterFriends = [];
  204. for (var i = 0; i < users.length; i++) {
  205. for (var x = 0; x < users[i].external_accounts.length; x++) {
  206. if (users[i].external_accounts[x].external_type === 'twitter') {
  207. twitterFriends.push(User.create({
  208. id: users[i].id,
  209. twitterId: parseInt(users[i].external_accounts[x].external_id, 10)
  210. }));
  211. break;
  212. }
  213. }
  214. }
  215. var lookupIds = twitterFriends.mapProperty('twitterId');
  216. twitter.request('1/users/lookup.json', { user_id: lookupIds.join(',') }, {}, 'POST', function(e) {
  217. if (e.success) {
  218. var json = JSON.parse(e.result.text);
  219. for (var i = 0; i < json.length; i++) {
  220. var user = twitterFriends.findProperty('twitterId', json[i].id);
  221. user.setProperties({
  222. name: json[i].name,
  223. avatarUrl: json[i].profile_image_url.replace('_normal', '')
  224. });
  225. }
  226. self.set('twitterFriends', twitterFriends);
  227. self.handleCallbacks(options);
  228. } else {
  229. self.handleError(e);
  230. self.handleCallbacks(options);
  231. }
  232. });
  233. } else {
  234. page++;
  235. getTwitterUsers(users);
  236. }
  237. } else {
  238. self.handleError(e);
  239. self.handleCallbacks(options);
  240. }
  241. });
  242. };
  243. getTwitterUsers();
  244. } else {
  245. self.handleError(e);
  246. self.handleCallbacks(options);
  247. }
  248. });
  249. },
  250.  
  251. /**
  252. Used to handle any callbacks required when passing
  253. options to any of UsersController's methods
  254.  
  255. @param {Hash} options
  256. Hash of options including button and callback.
  257. */
  258. handleCallbacks: function(options) {
  259. if (Ember.none(options)) return this;
  260. if (!Ember.none(options.button)) options.button.unclick();
  261. if (!Ember.none(options.callback)) options.callback();
  262. return this;
  263. },
  264.  
  265. /**
  266. Handle any errors thrown when registering a user or signing in.
  267.  
  268. @param {Object} error
  269. */
  270. handleError: function(error) {
  271. if (error.message) {
  272. alert(error.message);
  273. }
  274. Ti.API.warn(JSON.stringify(error));
  275. },
  276.  
  277. /**
  278. Link Facebook account to existing ACS user account.
  279. */
  280. linkFacebookAccount: function() {
  281. var user = this.get('content'), self = this;
  282.  
  283. Cloud.SocialIntegrations.externalAccountLink({
  284. id: user.get('facebookId'),
  285. type: 'facebook',
  286. token: user.get('facebookAccessToken')
  287. }, function (e) {
  288. if (e.success) {
  289. var user = e.users[0];
  290. self.saveUser(user);
  291. } else {
  292. self.handleError(e);
  293. }
  294. });
  295. },
  296.  
  297. /**
  298. Link Twitter account to existing ACS user account.
  299. */
  300. linkTwitterAccount: function() {
  301. var user = this.get('content'), self = this;
  302.  
  303. Cloud.SocialIntegrations.externalAccountLink({
  304. id: user.get('twitterId'),
  305. type: 'twitter',
  306. token: user.get('twitterAccessTokenKey')
  307. }, function (e) {
  308. if (e.success) {
  309. var user = e.users[0];
  310. self.saveUser(user);
  311. } else {
  312. self.handleError(e);
  313. }
  314. });
  315. },
  316.  
  317. /**
  318. Create an ACS user account.
  319.  
  320. @param {Hash} options
  321. Hash of options including button, and callback.
  322. */
  323. register: function(options) {
  324. var user = this.get('content'), self = this;
  325. Cloud.Users.create({
  326. first_name: user.get('name'),
  327. email: user.get('email'),
  328. password: user.get('password'),
  329. password_confirmation: user.get('passwordConfirmation')
  330. }, function (e) {
  331. if (e.success) {
  332. var user = e.users[0];
  333. self.saveUser(user);
  334. options.callback();
  335. } else {
  336. self.handleError(e);
  337. }
  338. options.button.unclick();
  339. });
  340. },
  341.  
  342. /**
  343. Save the logged in user.
  344.  
  345. @param {Object} userData
  346. ACS user object
  347. */
  348. saveUser: function(userData) {
  349. var user = this.get('content');
  350. user.set('id', userData.id);
  351. user.save();
  352. Ti.App.Properties.setString('acs-user-id', userData.id);
  353. },
  354.  
  355. /**
  356. Sign in to ACS.
  357. The method for signing in is determined by the `type` option.
  358.  
  359. @param {Hash} options
  360. Hash of options including type, button, and callback.
  361. */
  362. signIn: function(options) {
  363. var user = this.get('content'), self = this;
  364.  
  365. if (Ember.none(options)) {
  366. options = {};
  367. }
  368.  
  369. switch(options.type) {
  370. case 'acs':
  371. this.signInWithACS();
  372. break;
  373. case 'facebook':
  374. this.authorizeFacebook();
  375. break;
  376. case 'twitter':
  377. this.authorizeTwitter();
  378. break;
  379. default:
  380. // Try signing in with saved login info.
  381. var id = Ti.App.Properties.getString('acs-user-id', null);
  382.  
  383. user = User.find(id);
  384.  
  385. if (!Ember.none(user)) {
  386. this.set('content', user);
  387. if (!Ember.none(user.get('facebookId'))) {
  388. this.signInWithFacebook();
  389. } else if (!Ember.none(user.get('twitterId'))) {
  390. this.signInWithTwitter();
  391. } else if (!Ember.none(user.get('email'))) {
  392. var keychainItem = Keychain.createItem({ identifier: 'login' });
  393. user.set('password', keychainItem.valueData);
  394. this.signInWithACS();
  395. }
  396. }
  397. }
  398. this.handleCallbacks(options);
  399. },
  400.  
  401. /**
  402. Sign out of ACS, Facebook, and Twitter.
  403. */
  404. signOut: function(options) {
  405. Ti.API.warn('UsersController#signOut not implemented yet.');
  406. },
  407.  
  408. /**
  409. Sign in to ACS user account using email and password.
  410. */
  411. signInWithACS: function() {
  412. var user = this.get('content'), self = this;
  413.  
  414. Cloud.Users.login({
  415. login: user.get('email'),
  416. password: user.get('password')
  417. }, function (e) {
  418. if (e.success) {
  419. var user = e.users[0];
  420. self.saveUser(user);
  421. } else {
  422. self.handleError(e);
  423. }
  424. });
  425. },
  426.  
  427. /**
  428. Sign in to ACS user account using Facebook.
  429. */
  430. signInWithFacebook: function() {
  431. var user = this.get('content'), self = this;
  432.  
  433. Cloud.SocialIntegrations.externalAccountLogin({
  434. id: user.get('facebookId'),
  435. type: 'facebook',
  436. token: user.get('facebookAccessToken')
  437. }, function (e) {
  438. if (e.success) {
  439. var user = e.users[0];
  440. self.saveUser(user);
  441. } else {
  442. self.handleError(e);
  443. }
  444. });
  445. },
  446.  
  447. /**
  448. Sign in to ACS user account using Twitter.
  449. */
  450. signInWithTwitter: function() {
  451. var user = this.get('content'), self = this;
  452.  
  453. Cloud.SocialIntegrations.externalAccountLogin({
  454. id: user.get('twitterId'),
  455. type: 'twitter',
  456. token: user.get('twitterAccessTokenKey')
  457. }, function (e) {
  458. if (e.success) {
  459. var user = e.users[0];
  460. self.saveUser(user);
  461. } else {
  462. self.handleError(e);
  463. }
  464. });
  465. },
  466.  
  467. /**
  468. Unlink Facebook account to existing ACS user account.
  469.  
  470. @param {Hash} options
  471. Hash of options including button and callback.
  472. */
  473. unlinkFacebook: function(options) {
  474. var user = this.get('content'), self = this;
  475.  
  476. Cloud.SocialIntegrations.externalAccountUnlink({
  477. id: user.get('facebookId'),
  478. type: 'facebook'
  479. }, function (e) {
  480. if (e.success) {
  481. Ti.Facebook.logout();
  482. user.setProperties({ facebookId: null, facebookAccessToken: null });
  483. user.save();
  484. } else {
  485. self.handleError(e);
  486. }
  487. self.handleCallbacks(options);
  488. });
  489. },
  490.  
  491. /**
  492. Unlink Twitter account to existing ACS user account.
  493.  
  494. @param {Hash} options
  495. Hash of options including button and callback.
  496. */
  497. unlinkTwitter: function(options) {
  498. var user = this.get('content'), self = this;
  499.  
  500. Cloud.SocialIntegrations.externalAccountUnlink({
  501. id: user.get('twitterId'),
  502. type: 'twitter'
  503. }, function (e) {
  504. if (e.success) {
  505. Ti.App.Properties.removeProperty('twitterAccessTokenKey');
  506. Ti.App.Properties.removeProperty('twitterAccessTokenSecret');
  507. user.setProperties({ twitterId: null, twitterAccessTokenKey: null, twitterAccessTokenSecret: null });
  508. user.save();
  509. } else {
  510. self.handleError(e);
  511. }
  512. self.handleCallbacks(options);
  513. });
  514. }
  515. });
  516.  
  517. module.exports = UsersController;
Add Comment
Please, Sign In to add comment