Browse Source

WIP services refactor: rpc, csrf, page title

* csrf as service
* rpc as service
* add preload store to DI, inject into routes
* service access via this.service instead of get('service')
* misc code cleanups
! needs tests
Rafał Pitoń 10 years ago
parent
commit
27a14aa5aa
31 changed files with 194 additions and 175 deletions
  1. 1 2
      misago/emberapp/app/adapters/application.js
  2. 3 3
      misago/emberapp/app/controllers/activation/request-link.js
  3. 5 5
      misago/emberapp/app/controllers/forgotten-password/change-form.js
  4. 4 4
      misago/emberapp/app/controllers/index.js
  5. 13 12
      misago/emberapp/app/controllers/login-modal.js
  6. 16 0
      misago/emberapp/app/initializers/csrf-service.js
  7. 0 15
      misago/emberapp/app/initializers/dev-csrf-tokens.js
  8. 11 0
      misago/emberapp/app/initializers/misago-preloaded-data.js
  9. 1 1
      misago/emberapp/app/initializers/page-title-service.js
  10. 2 2
      misago/emberapp/app/initializers/rpc-service.js
  11. 33 0
      misago/emberapp/app/mixins/document-title.js
  12. 0 1
      misago/emberapp/app/router.js
  13. 6 6
      misago/emberapp/app/routes/activation/activate.js
  14. 9 9
      misago/emberapp/app/routes/activation/index.js
  15. 10 9
      misago/emberapp/app/routes/application.js
  16. 5 5
      misago/emberapp/app/routes/forgotten-password/change-form.js
  17. 3 3
      misago/emberapp/app/routes/forgotten-password/index.js
  18. 3 3
      misago/emberapp/app/routes/index.js
  19. 5 0
      misago/emberapp/app/routes/misago.js
  20. 2 2
      misago/emberapp/app/routes/not-found.js
  21. 3 3
      misago/emberapp/app/routes/privacy-policy.js
  22. 3 2
      misago/emberapp/app/routes/register.js
  23. 24 0
      misago/emberapp/app/services/csrf.js
  24. 4 2
      misago/emberapp/app/services/page-title.js
  25. 1 1
      misago/emberapp/app/services/rpc.js
  26. 1 0
      misago/emberapp/app/templates/misago.hbs
  27. 0 7
      misago/emberapp/app/utils/csrf.js
  28. 0 48
      misago/emberapp/tests/unit/initializers/dev-csrf-tokens-test.js
  29. 12 0
      misago/emberapp/tests/unit/mixins/document-title-test.js
  30. 14 0
      misago/emberapp/tests/unit/routes/misago-test.js
  31. 0 30
      misago/emberapp/tests/unit/utils/csrf-test.js

+ 1 - 2
misago/emberapp/app/adapters/application.js

@@ -1,11 +1,10 @@
 import Ember from 'ember';
 import Ember from 'ember';
 import DRFAdapter from './drf';
 import DRFAdapter from './drf';
-import getCsrfToken from 'misago/utils/csrf';
 
 
 export default DRFAdapter.extend({
 export default DRFAdapter.extend({
   headers: function() {
   headers: function() {
     return {
     return {
-      'X-CSRFToken': getCsrfToken()
+      'X-CSRFToken': this.get('csrf.token')
     };
     };
   }.property().volatile(),
   }.property().volatile(),
 
 

+ 3 - 3
misago/emberapp/app/controllers/activation/request-link.js

@@ -14,14 +14,14 @@ export default Ember.ObjectController.extend({
       var email = Ember.$.trim(this.get('email'));
       var email = Ember.$.trim(this.get('email'));
 
 
       if (email === "") {
       if (email === "") {
-        this.get('toast').warning(gettext("Enter e-mail address."));
+        this.toast.warning(gettext("Enter e-mail address."));
         return;
         return;
       }
       }
 
 
       this.set('isLoading', true);
       this.set('isLoading', true);
 
 
       var self = this;
       var self = this;
-      this.get('rpc').ajax(this.get('rpcUrl'), {
+      this.rpc.ajax(this.get('rpcUrl'), {
         email: email
         email: email
       }).then(function(requestingUser) {
       }).then(function(requestingUser) {
         self.send('success', requestingUser);
         self.send('success', requestingUser);
@@ -44,7 +44,7 @@ export default Ember.ObjectController.extend({
           this.send('showBan', rejection.detail);
           this.send('showBan', rejection.detail);
           this.set('email', '');
           this.set('email', '');
         } else {
         } else {
-          this.get('toast').error(rejection.detail);
+          this.toast.error(rejection.detail);
         }
         }
       } else {
       } else {
         this.send('toastError', jqXHR);
         this.send('toastError', jqXHR);

+ 5 - 5
misago/emberapp/app/controllers/forgotten-password/change-form.js

@@ -17,14 +17,14 @@ export default Ember.ObjectController.extend({
       var password = Ember.$.trim(this.get('password'));
       var password = Ember.$.trim(this.get('password'));
 
 
       if (password === "") {
       if (password === "") {
-        this.get('toast').warning(gettext("Enter new password."));
+        this.toast.warning(gettext("Enter new password."));
         return;
         return;
       }
       }
 
 
       this.set('isLoading', true);
       this.set('isLoading', true);
 
 
       var self = this;
       var self = this;
-      this.get('rpc').ajax(this.get('change_password_url'), {
+      this.rpc.ajax(this.get('change_password_url'), {
         password: password
         password: password
       }).then(function() {
       }).then(function() {
         self.send('success');
         self.send('success');
@@ -39,16 +39,16 @@ export default Ember.ObjectController.extend({
       this.set('password', '');
       this.set('password', '');
 
 
       this.send('openLoginModal');
       this.send('openLoginModal');
-      this.get('toast').success(gettext("Your password has been changed."));
+      this.toast.success(gettext("Your password has been changed."));
     },
     },
 
 
     error: function(jqXHR) {
     error: function(jqXHR) {
       var rejection = jqXHR.responseJSON;
       var rejection = jqXHR.responseJSON;
       if (jqXHR.status === 400){
       if (jqXHR.status === 400){
-        this.get('toast').error(rejection.detail);
+        this.toast.error(rejection.detail);
       } else {
       } else {
         if (jqXHR.status === 404) {
         if (jqXHR.status === 404) {
-          this.get('toast').error(rejection.detail);
+          this.toast.error(rejection.detail);
           this.transitionTo('forgotten-password');
           this.transitionTo('forgotten-password');
         } else {
         } else {
           this.send('toastError', jqXHR);
           this.send('toastError', jqXHR);

+ 4 - 4
misago/emberapp/app/controllers/index.js

@@ -3,19 +3,19 @@ import Ember from 'ember';
 export default Ember.Controller.extend({
 export default Ember.Controller.extend({
   actions: {
   actions: {
     testInfo: function() {
     testInfo: function() {
-      this.get('toast').info(this.get('newFlash'));
+      this.toast.info(this.get('newFlash'));
     },
     },
 
 
     testSuccess: function() {
     testSuccess: function() {
-      this.get('toast').success(this.get('newFlash'));
+      this.toast.success(this.get('newFlash'));
     },
     },
 
 
     testWarning: function() {
     testWarning: function() {
-      this.get('toast').warning(this.get('newFlash'));
+      this.toast.warning(this.get('newFlash'));
     },
     },
 
 
     testError: function() {
     testError: function() {
-      this.get('toast').error(this.get('newFlash'));
+      this.toast.error(this.get('newFlash'));
     }
     }
   }
   }
 });
 });

+ 13 - 12
misago/emberapp/app/controllers/login-modal.js

@@ -1,5 +1,4 @@
 import Ember from 'ember';
 import Ember from 'ember';
-import getCsrfToken from 'misago/utils/csrf';
 
 
 export default Ember.Controller.extend({
 export default Ember.Controller.extend({
   modal: null,
   modal: null,
@@ -28,11 +27,13 @@ export default Ember.Controller.extend({
   },
   },
 
 
   reset: function() {
   reset: function() {
-    this.set('username', '');
-    this.set('password', '');
+    this.setProperties({
+      'username': '',
+      'password': '',
 
 
-    this.set('isLoading', false);
-    this.set('showActivation', false);
+      'isLoading': false,
+      'showActivation': false
+    });
   },
   },
 
 
   actions: {
   actions: {
@@ -51,12 +52,12 @@ export default Ember.Controller.extend({
       };
       };
 
 
       if (!credentials.username || !credentials.password) {
       if (!credentials.username || !credentials.password) {
-        this.get('toast').warning(gettext("Fill out both fields."));
+        this.toast.warning(gettext("Fill out both fields."));
         return;
         return;
       }
       }
 
 
       var self = this;
       var self = this;
-      this.get('rpc').ajax(this.get('settings.loginApiUrl'), credentials
+      this.rpc.ajax(this.get('settings.loginApiUrl'), credentials
       ).then(function() {
       ).then(function() {
         self.send('success', credentials);
         self.send('success', credentials);
       }, function(jqXHR) {
       }, function(jqXHR) {
@@ -69,8 +70,8 @@ export default Ember.Controller.extend({
     success: function(credentials) {
     success: function(credentials) {
       var $form = Ember.$('#hidden-login-form');
       var $form = Ember.$('#hidden-login-form');
 
 
-      // we need to refresh CSRF token because previous api call changed it
-      $form.find('input[name=csrfmiddlewaretoken]').val(getCsrfToken());
+      // refresh CSRF token because parent api call changed it
+      this.csrf.updateFormToken($form);
 
 
       // fill out form with user credentials and submit it, this will tell
       // fill out form with user credentials and submit it, this will tell
       // misago to redirect user back to right page, and will trigger browser's
       // misago to redirect user back to right page, and will trigger browser's
@@ -86,9 +87,9 @@ export default Ember.Controller.extend({
       if (jqXHR.status !== 400) {
       if (jqXHR.status !== 400) {
         this.send('toastError', jqXHR);
         this.send('toastError', jqXHR);
       } else if (rejection.code === 'inactive_admin') {
       } else if (rejection.code === 'inactive_admin') {
-        this.get('toast').info(rejection.detail);
+        this.toast.info(rejection.detail);
       } else if (rejection.code === 'inactive_user') {
       } else if (rejection.code === 'inactive_user') {
-        this.get('toast').info(rejection.detail);
+        this.toast.info(rejection.detail);
         this.set('showActivation', true);
         this.set('showActivation', true);
       } else if (rejection.code === 'banned') {
       } else if (rejection.code === 'banned') {
         this.send('showBan', rejection.detail);
         this.send('showBan', rejection.detail);
@@ -96,7 +97,7 @@ export default Ember.Controller.extend({
           Ember.$('#loginModal').modal('hide');
           Ember.$('#loginModal').modal('hide');
         });
         });
       } else {
       } else {
-        this.get('toast').error(rejection.detail);
+        this.toast.error(rejection.detail);
       }
       }
       return false;
       return false;
     },
     },

+ 16 - 0
misago/emberapp/app/initializers/csrf-service.js

@@ -0,0 +1,16 @@
+import CSRFService from 'misago/services/csrf';
+
+export function initialize(container, application) {
+  application.register('service:csrf', CSRFService, { singleton: true });
+
+  application.inject('service:csrf', 'preloadedStore', 'misago:preloaded-data');
+
+  [ 'controller', 'adapter' ].forEach((factory) => {
+    application.inject(factory, 'csrf', 'service:csrf');
+  });
+}
+
+export default {
+  name: 'csrf-service',
+  initialize: initialize
+};

+ 0 - 15
misago/emberapp/app/initializers/dev-csrf-tokens.js

@@ -1,15 +0,0 @@
-import Ember from 'ember';
-import getCsrfToken from 'misago/utils/csrf';
-import ENV from '../config/environment';
-
-export function initialize() {
-  if (ENV.environment !== 'production') {
-    // set initial CSRF tokens on preloaded forms
-    Ember.$('input[name=csrfmiddlewaretoken]').val(getCsrfToken());
-  }
-}
-
-export default {
-  name: 'dev-csrf-tokens',
-  initialize: initialize
-};

+ 11 - 0
misago/emberapp/app/initializers/misago-preloaded-data.js

@@ -0,0 +1,11 @@
+import MisagoPreloadStore from 'misago/utils/preloadstore';
+
+export function initialize(container, application) {
+  application.register('misago:preload-store', MisagoPreloadStore, { instantiate: false });
+  application.inject('route', 'preloadStore', 'misago:preload-store');
+}
+
+export default {
+  name: 'misago-preloaded-data',
+  initialize: initialize
+};

+ 1 - 1
misago/emberapp/app/initializers/page-title-service.js

@@ -4,7 +4,7 @@ export function initialize(container, application) {
   application.inject('service:page-title', 'settings', 'misago:settings');
   application.inject('service:page-title', 'settings', 'misago:settings');
 
 
   application.register('service:page-title', PageTitleService, { singleton: true });
   application.register('service:page-title', PageTitleService, { singleton: true });
-  application.inject('route', 'page-title', 'service:page-title');
+  application.inject('route', 'title', 'service:page-title');
 }
 }
 
 
 export default {
 export default {

+ 2 - 2
misago/emberapp/app/initializers/rpc-service.js

@@ -1,7 +1,7 @@
-import RpcService from 'misago/services/rpc';
+import RPCService from 'misago/services/rpc';
 
 
 export function initialize(_container, application) {
 export function initialize(_container, application) {
-  application.register('service:rpc', RpcService, { singleton: true });
+  application.register('service:rpc', RPCService, { singleton: true });
 
 
   application.inject('service:rpc', 'store', 'store:main');
   application.inject('service:rpc', 'store', 'store:main');
 
 

+ 33 - 0
misago/emberapp/app/mixins/document-title.js

@@ -0,0 +1,33 @@
+import Ember from 'ember';
+
+export default Ember.Mixin.create({
+  title: function(key, value) {
+    // setter
+    if (arguments.length > 1) {
+      this._changeTitle(value);
+    }
+
+    // getter
+    return document.title;
+  }.property(),
+
+  _changeTitle: function(title) {
+    if (typeof title === 'string') {
+      title = {title: title};
+    }
+
+    var complete_title = title.title;
+
+    if (typeof title.page !== 'undefined') {
+      complete_title += ' (' + interpolate(gettext('page %(page)s'), {page:title.page}, true) + ')';
+    }
+
+    if (typeof title.parent !== 'undefined') {
+      complete_title += ' | ' + title.parent;
+    }
+
+    complete_title += ' | ' + this.get('settings.forum_name');
+
+    document.title = complete_title;
+  }
+});

+ 0 - 1
misago/emberapp/app/router.js

@@ -28,7 +28,6 @@ Router.map(function() {
   this.route('error-404', { path: 'error-404/' });
   this.route('error-404', { path: 'error-404/' });
   this.route('error-banned', { path: 'banned/:reason/' });
   this.route('error-banned', { path: 'banned/:reason/' });
   this.route('not-found', { path: '*path' });
   this.route('not-found', { path: '*path' });
-  this.route('register');
 });
 });
 
 
 export default Router;
 export default Router;

+ 6 - 6
misago/emberapp/app/routes/activation/activate.js

@@ -1,26 +1,26 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   model: function(params) {
   model: function(params) {
-    return this.get('rpc').ajax('activation/' + params.user_id + '/' + params.token + '/validate-token');
+    return this.rpc.ajax('activation/' + params.user_id + '/' + params.token + '/validate-token');
   },
   },
 
 
   afterModel: function(model) {
   afterModel: function(model) {
     this.send('openLoginModal');
     this.send('openLoginModal');
-    this.get('toast').success(model.detail);
+    this.toast.success(model.detail);
     return this.transitionTo('index');
     return this.transitionTo('index');
   },
   },
 
 
   actions: {
   actions: {
     loading: function() {
     loading: function() {
-      this.get('page-title').setTitle(gettext('Activating account...'));
+      this.set('title', gettext('Activating account...'));
       return true;
       return true;
     },
     },
 
 
     error: function(reason) {
     error: function(reason) {
       if (reason.status === 404) {
       if (reason.status === 404) {
-        this.get('toast').error(reason.responseJSON.detail);
+        this.toast.error(reason.responseJSON.detail);
         return this.transitionTo('activation');
         return this.transitionTo('activation');
       }
       }
 
 

+ 9 - 9
misago/emberapp/app/routes/activation/index.js

@@ -1,25 +1,25 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
-  title: gettext('Request activation link'),
-  templateName: 'activation.request-link',
+export default MisagoRoute.extend(ResetScroll, {
+  formTitle: gettext('Request activation link'),
+  formTemplate: 'activation.request-link',
 
 
   sentTitle: gettext('Activation link sent'),
   sentTitle: gettext('Activation link sent'),
-  sentTemplateName: 'activation.link-sent',
+  sentTemplate: 'activation.link-sent',
 
 
   renderTemplate: function() {
   renderTemplate: function() {
-    this.render(this.get('templateName'));
+    this.render(this.get('formTemplate'));
   },
   },
 
 
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
-      this.get('page-title').setTitle(this.get('title'));
+      this.set('title', this.get('formTitle'));
     },
     },
 
 
     showSentPage: function(linkRecipient) {
     showSentPage: function(linkRecipient) {
-      this.get('page-title').setTitle(this.get('sentTitle'));
-      this.render(this.get('sentTemplateName'), {
+      this.set('title', this.get('sentTitle'));
+      this.render(this.get('sentTemplate'), {
         model: linkRecipient
         model: linkRecipient
       });
       });
     },
     },

+ 10 - 9
misago/emberapp/app/routes/application.js

@@ -1,11 +1,12 @@
 import Ember from 'ember';
 import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 
 
-export default Ember.Route.extend({
+export default MisagoRoute.extend({
   actions: {
   actions: {
     // Loading handler
     // Loading handler
 
 
     loading: function() {
     loading: function() {
-      this.get('page-title').setPlaceholderTitle();
+      document.title = this.get('settings.forum_name');
       return true;
       return true;
     },
     },
 
 
@@ -13,17 +14,17 @@ export default Ember.Route.extend({
 
 
     error: function(reason) {
     error: function(reason) {
       if (reason.status === 0) {
       if (reason.status === 0) {
-        this.get('page-title').setTitle(gettext('Connection lost'));
+        this.set('title', gettext('Connection lost'));
         return this.intermediateTransitionTo('error-0');
         return this.intermediateTransitionTo('error-0');
       }
       }
 
 
       if (typeof reason.responseJSON !== 'undefined' && typeof reason.responseJSON.ban !== 'undefined') {
       if (typeof reason.responseJSON !== 'undefined' && typeof reason.responseJSON.ban !== 'undefined') {
-        this.get('page-title').setTitle(gettext('You are banned'));
+        this.set('title', gettext('You are banned'));
         return this.intermediateTransitionTo('error-banned', reason.responseJSON.ban);
         return this.intermediateTransitionTo('error-banned', reason.responseJSON.ban);
       }
       }
 
 
       if (reason.status === 403) {
       if (reason.status === 403) {
-        this.get('page-title').setTitle(gettext('Page not available'));
+        this.set('title', gettext('Page not available'));
 
 
         var final_error = {status: 403, message: null};
         var final_error = {status: 403, message: null};
         if (typeof reason.responseJSON !== 'undefined' && typeof reason.responseJSON.detail !== 'undefined' && reason.responseJSON.detail !== 'Permission denied') {
         if (typeof reason.responseJSON !== 'undefined' && typeof reason.responseJSON.detail !== 'undefined' && reason.responseJSON.detail !== 'Permission denied') {
@@ -34,11 +35,11 @@ export default Ember.Route.extend({
       }
       }
 
 
       if (reason.status === 404) {
       if (reason.status === 404) {
-        this.get('page-title').setTitle(gettext('Page not found'));
+        this.set('title', gettext('Page not found'));
         return this.intermediateTransitionTo('error-404');
         return this.intermediateTransitionTo('error-404');
       }
       }
 
 
-      this.get('page-title').setTitle(gettext('Error'));
+      this.set('title', gettext('Error'));
       return true;
       return true;
     },
     },
 
 
@@ -61,11 +62,11 @@ export default Ember.Route.extend({
         errorMessage = gettext('Action link is invalid.');
         errorMessage = gettext('Action link is invalid.');
       }
       }
 
 
-      this.get('toast').error(errorMessage);
+      this.toast.error(errorMessage);
     },
     },
 
 
     showBan: function(ban) {
     showBan: function(ban) {
-      this.get('page-title').setTitle(gettext('You are banned'));
+      this.set('title', gettext('You are banned'));
       this.intermediateTransitionTo('error-banned', ban);
       this.intermediateTransitionTo('error-banned', ban);
     },
     },
 
 

+ 5 - 5
misago/emberapp/app/routes/forgotten-password/change-form.js

@@ -1,19 +1,19 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   model: function(params) {
   model: function(params) {
-    return this.get('rpc').ajax('change-password/' + params.user_id + '/' + params.token + '/validate-token');
+    return this.rpc.ajax('change-password/' + params.user_id + '/' + params.token + '/validate-token');
   },
   },
 
 
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
-      this.get('page-title').setTitle(gettext('Change forgotten password'));
+      this.set('title', gettext('Change forgotten password'));
     },
     },
 
 
     error: function(reason) {
     error: function(reason) {
       if (reason.status === 404) {
       if (reason.status === 404) {
-        this.get('toast').error(reason.responseJSON.detail);
+        this.toast.error(reason.responseJSON.detail);
         return this.transitionTo('forgotten-password');
         return this.transitionTo('forgotten-password');
       }
       }
 
 

+ 3 - 3
misago/emberapp/app/routes/forgotten-password/index.js

@@ -1,9 +1,9 @@
 import RequestLinkRoute from 'misago/routes/activation/index';
 import RequestLinkRoute from 'misago/routes/activation/index';
 
 
 export default RequestLinkRoute.extend({
 export default RequestLinkRoute.extend({
-  title: gettext('Change forgotten password'),
-  templateName: 'forgotten-password.request-link',
+  formTitle: gettext('Change forgotten password'),
+  formTemplate: 'forgotten-password.request-link',
 
 
   sentTitle: gettext('Change password form link sent'),
   sentTitle: gettext('Change password form link sent'),
-  sentTemplateName: 'forgotten-password.link-sent'
+  sentTemplate: 'forgotten-password.link-sent'
 });
 });

+ 3 - 3
misago/emberapp/app/routes/index.js

@@ -1,10 +1,10 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
-      this.get('page-title').setIndexTitle();
+      document.title = this.get('settings.forum_index_title') || this.get('settings.forum_name');
     }
     }
   }
   }
 });
 });

+ 5 - 0
misago/emberapp/app/routes/misago.js

@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import DocumentTitle from 'misago/mixins/document-title';
+
+export default Ember.Route.extend(DocumentTitle, {
+});

+ 2 - 2
misago/emberapp/app/routes/not-found.js

@@ -1,7 +1,7 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
       // Not found route transitions to error404
       // Not found route transitions to error404

+ 3 - 3
misago/emberapp/app/routes/privacy-policy.js

@@ -1,7 +1,7 @@
-import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   page: 'privacy-policy',
   page: 'privacy-policy',
   defaultTitle: gettext('Privacy policy'),
   defaultTitle: gettext('Privacy policy'),
 
 
@@ -37,7 +37,7 @@ export default Ember.Route.extend(ResetScroll, {
 
 
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
-      this.get('page-title').setTitle(this.get('title'));
+      this.set('title', this.get('title'));
     }
     }
   }
   }
 });
 });

+ 3 - 2
misago/emberapp/app/routes/register.js

@@ -1,7 +1,8 @@
 import Ember from 'ember';
 import Ember from 'ember';
+import MisagoRoute from 'misago/routes/misago';
 import ResetScroll from 'misago/mixins/reset-scroll';
 import ResetScroll from 'misago/mixins/reset-scroll';
 
 
-export default Ember.Route.extend(ResetScroll, {
+export default MisagoRoute.extend(ResetScroll, {
   stage: 'form',
   stage: 'form',
 
 
   isForm: Ember.computed.equal('stage', 'form'),
   isForm: Ember.computed.equal('stage', 'form'),
@@ -26,7 +27,7 @@ export default Ember.Route.extend(ResetScroll, {
 
 
   actions: {
   actions: {
     didTransition: function() {
     didTransition: function() {
-      this.get('page-title').setTitle(gettext("Register"));
+      this.set('title', gettext("Register"));
     }
     }
   }
   }
 });
 });

+ 24 - 0
misago/emberapp/app/services/csrf.js

@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import ENV from '../config/environment';
+
+export default Ember.Object.extend({
+  cookieName: function() {
+    return this.preloadStore.get('csrfCookieName');
+  }.property.volatile(),
+
+  token: function() {
+    var regex = new RegExp(this.get('cookieName') + '\=([^;]*)');
+    return Ember.get(document.cookie.match(regex), "1");
+  }.property().volatile(),
+
+  init: function() {
+    if (ENV.environment !== 'production') {
+      // set initial CSRF tokens on preloaded forms in dev
+      Ember.$('input[name=csrfmiddlewaretoken]').val(this.get('token'));
+    }
+  },
+
+  updateFormToken: function($form) {
+    $form.find('input[name=csrfmiddlewaretoken]').val(this.get('token'));
+  }
+});

+ 4 - 2
misago/emberapp/app/services/page-title.js

@@ -5,8 +5,10 @@ export default Ember.Service.extend({
   forumName: '',
   forumName: '',
 
 
   init: function() {
   init: function() {
-    this.set('indexTitle', this.get('settings.forum_index_title'));
-    this.set('forumName', this.get('settings.forum_name'));
+    this.setProperties({
+      'indexTitle': this.get('settings.forum_index_title'),
+      'forumName': this.get('settings.forum_name')
+    });
   },
   },
 
 
   setTitle: function(title) {
   setTitle: function(title) {

+ 1 - 1
misago/emberapp/app/services/rpc.js

@@ -18,7 +18,7 @@ export default Ember.Object.extend({
     // note: in case of Model being null this cheats adapterFor to return
     // note: in case of Model being null this cheats adapterFor to return
     // 'adapter:application'. we are doing this, because for some reason
     // 'adapter:application'. we are doing this, because for some reason
     // store.defaultAdapter fails to return django adapter
     // store.defaultAdapter fails to return django adapter
-    var adapter = this.get('store').adapterFor(record || {typeKey: 'application'});
+    var adapter = this.store.adapterFor(record || {typeKey: 'application'});
 
 
     // build api call URL
     // build api call URL
     var url = null;
     var url = null;

+ 1 - 0
misago/emberapp/app/templates/misago.hbs

@@ -0,0 +1 @@
+{{outlet}}

+ 0 - 7
misago/emberapp/app/utils/csrf.js

@@ -1,7 +0,0 @@
-import Ember from 'ember';
-import MisagoPreloadStore from 'misago/utils/preloadstore';
-
-export default function getCsrfToken() {
-  var regex = new RegExp(MisagoPreloadStore.get('csrfCookieName') + '\=([^;]*)');
-  return Ember.get(document.cookie.match(regex), "1");
-}

+ 0 - 48
misago/emberapp/tests/unit/initializers/dev-csrf-tokens-test.js

@@ -1,48 +0,0 @@
-import Ember from 'ember';
-import { initialize } from '../../../initializers/dev-csrf-tokens';
-import MisagoPreloadStore from '../../../utils/preloadstore';
-import { module, test } from 'qunit';
-
-var container, application;
-
-var cookieName = MisagoPreloadStore.get('csrfCookieName');
-
-var testCookieName = 'devcsrftokenCookie';
-var testCookieValue = 't3stW0rk5';
-
-var $element = null;
-
-module('devCsrfTokensInitializer', {
-  beforeEach: function() {
-    // assert csrf token exists:
-    MisagoPreloadStore.set('csrfCookieName', testCookieName);
-    document.cookie = testCookieName + '=' + testCookieValue + ';';
-
-    // set test element
-    $element = Ember.$('<input type="hidden" name="csrfmiddlewaretoken">');
-    Ember.$('#ember-testing').append($element);
-
-    // prepare app
-    Ember.run(function() {
-      application = Ember.Application.create();
-      container = application.__container__;
-      application.deferReadiness();
-    });
-  },
-
-  afterEach: function() {
-    MisagoPreloadStore.set('csrfCookieName', cookieName);
-    $element.remove();
-  }
-});
-
-test('sets tokens on predefined forms', function(assert) {
-  assert.expect(1);
-  var done = assert.async();
-
-  Ember.run(function() {
-    initialize();
-    assert.equal($element.val(), testCookieValue);
-    done();
-  });
-});

+ 12 - 0
misago/emberapp/tests/unit/mixins/document-title-test.js

@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import DocumentTitleMixin from '../../../mixins/document-title';
+import { module, test } from 'qunit';
+
+module('DocumentTitleMixin');
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+  var DocumentTitleObject = Ember.Object.extend(DocumentTitleMixin);
+  var subject = DocumentTitleObject.create();
+  assert.ok(subject);
+});

+ 14 - 0
misago/emberapp/tests/unit/routes/misago-test.js

@@ -0,0 +1,14 @@
+import {
+  moduleFor,
+  test
+} from 'ember-qunit';
+
+moduleFor('route:misago', {
+  // Specify the other units that are required for this test.
+  // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+  var route = this.subject();
+  assert.ok(route);
+});

+ 0 - 30
misago/emberapp/tests/unit/utils/csrf-test.js

@@ -1,30 +0,0 @@
-import getCsrfToken from '../../../utils/csrf';
-import MisagoPreloadStore from '../../../utils/preloadstore';
-import { module, test } from 'qunit';
-
-var cookieName = MisagoPreloadStore.get('csrfCookieName');
-
-module('csrf', {
-  afterEach: function() {
-    MisagoPreloadStore.set('csrfCookieName', cookieName);
-  }
-});
-
-test('getCsrfToken function returns csrf token', function(assert) {
-  assert.expect(1);
-
-  var cookieName = 'validcsrfcookie';
-  var token = 'v4l1dc5rft0k3n';
-
-  MisagoPreloadStore.set('csrfCookieName', cookieName);
-
-  document.cookie = cookieName + '=' + token + ';';
-  assert.equal(getCsrfToken(), token);
-});
-
-test('getCsrfToken function returns undefined for non-existing cookie', function(assert) {
-  assert.expect(1);
-
-  MisagoPreloadStore.set('csrfCookieName', 'n0n3x15t1ng');
-  assert.equal(getCsrfToken(), undefined);
-});