Custom Session interfering with acceptance tests - ember-cli

I am using ember-cli-simple-auth and ember-cli-simple-auth-devise in an ember-cli project.
I'm also customizing simple-auth's Session via an initializer:
// app/initializers/custom-session.js
import Ember from 'ember';
import Session from 'simple-auth/session';
export default {
name: 'custom-session',
before: 'simple-auth',
initialize: function(container, application) {
Session.reopen({
setCurrentUser: function() {
var id = this.get('user_id'),
self = this;
if (!Ember.isEmpty(id)) {
return container.lookup('store:main').find('user', id)
.then(function(user) {
self.set('currentUser', user);
});
}
}.observes('user_id')
});
}
};
In a simple acceptance test (one that simply calls ok(1)), I'm getting the following error
Error: Assertion Failed: calling set on destroyed object
Source:
at Adapter.extend.exception (localhost:4900/assets/vendor.js:57907:19)
at apply (http://localhost:4900/assets/vendor.js:21143:27)
at superWrapper [as exception] (localhost:4900/assets/vendor.js:20721:15)
at RSVP.onerrorDefault (localhost:4900/assets/vendor.js:59827:26)
at Object.__exports__.default.trigger (localhost:4900/assets/vendor.js:22673:13)
at Promise._onerror (localhost:4900/assets/vendor.js:23397:16)
at publishRejection (localhost:4900/assets/vendor.js:23804:17)
at http://localhost:4900/assets/vendor.js:29217:9
If I comment out the self.set('currentUser', user); line, the error goes away.
What's the appropriate way to handle this? Is there a way to ignore this initializer in tests?
I also get this log message:
No authorizer factory was configured for Ember Simple Auth - specify one if backend requests need to be authorized.

First of all you should update Ember Simple Auth to the latest version 0.6.4 that allows you to specify a custom session class without having to reopen the default Session: https://github.com/simplabs/ember-simple-auth/releases/tag/0.6.4.
Secondly, the warning about the authorizer simply means that requests going to a backend server will not be authorized (e.g. will not have an Authorization header) as no authorizer is defined. That might be ok though depending on your setup.
Regarding the destroyed object problem you could simply check whether the object is destroyed:
if (!self.isDestroyed) {
self.set('currentUser', user);
}

Related

Using angular2-sails module for realtime communication using sockets

I would like to use sails.io.js with angular5, so I used angular2-sails module. I managed to connect angular to sails but I didn't manage to retrieve the events from sails.js, for example when a new document is created in database. Is there something to configure sails side ? I used this.sailsService.on("user").subscribe(data => console.log("event on user")). The get and post methods are perfectly working. Sails side I put
ioclient: require('socket.io-client')('http://localhost:1337'),
io: require('sails.io.js'),
In config/http.js, instead of
var io = require('sails.io.js')( require('socket.io-client') );
because else sails cannot load
I didn't write anything in config/socket.js
angular2-sails module is deprecated so I used the io variable from sails.io.js using a service :
import {Injectable} from '#angular/core';
function _window(): any {
// return the global native browser window object
return window;
}
#Injectable()
export class SocketService {
get ioSails(): any {
return _window().io;
}
}

Ember. Inject an addon service into additional 'areas'

How would I inject an addon service into other 'places'?
For example, if I install an addon that injects into controllers & components with the code below:
export default {
name: 'notification-messages-service',
initialize() {
let application = arguments[1] || arguments[0];
application.register('notification-messages:service', NotificationMessagesService);
['controller', 'component'].forEach(injectionTarget => {
application.inject(injectionTarget, 'notifications', 'notification-messages:service');
});
}};
How would I then inject the same service (the same singleton) into services & routes - my requirement is actually inject into a single service, services:messages?
I don't believe I can use
notifications: Ember.inject.service();
because in the addon the service is written as:
export default Ember.ArrayProxy.extend({...});
I can change the addon, of course, but my changes would be gone once the addon is updated.
Thanks for looking, N
notifications: Ember.inject.service('notification-messages');
should work
param for service is optional if name of service the same as property name, but it's bette always use it
P.S. code above for normal services
in you case code
['controller', 'component'].forEach(injectionTarget => {
application.inject(injectionTarget, 'notifications', 'notification-messages:service');
});
means that controllers/components just get new property notifications
So inside your controllers/components you can use
this.get('notifications')
I was able to inject the addon to my specific service by creating a new initialiser with the code below:
export default {
name: 'inject-ember-notification-service',
initialize: function(container, app) {
app.inject('services:message', 'notifications', 'notification-messages:service');
}
};
Fiendishly obtuse, ember!
Thanks to you all for your input.

Customizing Autofac in Azure mobile app results in 'No service registered for ITableControllerConfigProvider type' exception

I'm trying to customize an Azure Web app application that was created with Visual Studio. I've added an AccountsController to help with user registration using the Owin membership tables. I want to add Owin to the site, so I'm customizing the WebApiConfig.cs file with this method:
public static void Register(HttpConfiguration config)
{
// Use this class to set configuration options for your mobile service
var options = new ConfigOptions();
var configBuilder = new ConfigBuilder(options, (configuration, builder) =>
{
var executingAssembly = Assembly.GetExecutingAssembly();
var file = FileHelper.GetLoggingConfigFile(executingAssembly);
// startup the logging
_logger = new Logger(MethodBase.GetCurrentMethod().DeclaringType, file);
//builder.RegisterInstance(new CustomOwinAppBuilder(configuration))
// .As<IOwinAppBuilder>();
//configure the Autofac IoC container
AutofacBuilder.Configure(executingAssembly, _logger, builder, new MvcModule(),
new TaskModule());
});
var defaultConfig = ServiceConfig.Initialize(configBuilder);
// Make sure this is after ServiceConfig.Initialize
// Otherwise ServiceConfig.Initialize will overwrite your changes
StartupOwinAppBuilder.Initialize(app =>
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(TrainMobileContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// app.UseFacebookAuthentication("", "");
});
defaultConfig.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// To display errors in the browser during development, uncomment the following
// line. Comment it out again when you deploy your service for production use.
// config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
Database.SetInitializer(new MobileServiceInitializer());
}
The AutofacBuilder handles a lot of the registration with statements like so:
builder.RegisterType<RepositoryProvider>().As<IRepositoryProvider>().InstancePerHttpRequest();
builder.RegisterType<DataManager>().As<IDataManager>().InstancePerHttpRequest();
builder.RegisterType<Logger>().As<ILogger>().InstancePerLifetimeScope();
// new TrainMobileUserStore(context.Get<SpaceLinxContext>())
builder.RegisterControllers(assembly).InstancePerHttpRequest();
builder.RegisterApiControllers(assembly);
builder.RegisterModelBinders(assembly).InstancePerHttpRequest();
builder.RegisterType<LogAttribute>().PropertiesAutowired();
builder.RegisterFilterProvider();
// Needed to allow property injection in custom action filters.
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(assembly).InjectActionInvoker();
When I've made these changes however, two things happen:
Firstly, the default azure mobile app default helper page disappears and I get a default page with this:
HTTP Error 403.14 - Forbidden
The Web server is configured to not list the contents of this directory.
Secondly, when I attempt to call the Help pages or AccountsController directly, a runtime exception is raised:
System.InvalidOperationException occurred
HResult=-2146233079
Message=No service registered for type 'ITableControllerConfigProvider'.Please ensure that the dependency resolver has been configured correctly.
Source=Microsoft.WindowsAzure.Mobile.Service
StackTrace:
at System.Web.Http.DependencyScopeExtensions.GetServiceOrThrow[TService](IDependencyScope services)
at Microsoft.WindowsAzure.Mobile.Service.Tables.TableControllerConfigAttribute.Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
at System.Web.Http.Controllers.HttpControllerDescriptor..ctor(HttpConfiguration configuration, String controllerName, Type controllerType)
at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.InitializeControllerInfoCache()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping()
at System.Web.Http.Description.ApiExplorer.InitializeApiDescriptions()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Web.Http.Description.ApiExplorer.get_ApiDescriptions()
at MyMobileApp.Mvc.Areas.HelpPage.Controllers.HelpController.Index() in C:\tfs\MyMobileApp\dotNET\Web\MyMobileApp.Mvc\Areas\HelpPage\Controllers\HelpController.cs:line 31
InnerException:
Does anyone know what the problem with this could be? Do I need to explicitly register the mobile service assemblies and if so, what's the best way of doing that?
This is now resolved.
Just to wrap this up, the basic problem was that I'd changed the WebApiConfig.Register method so that it was non standard. I'd changed it from this
public static void Register()
to this
public static void Register(HttpConfiguration config)
and was attempting to use it like one would a standard Mvc webapi configuration from Global.asax.cs
Once I changed it back, I was able to register objects using autofac in the method like this:
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<ApplicationContext>())).AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
{
DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("Application​")
});
without any problem
thanks

Play Framework redirect not working in Safari

I'm attempting to query Solr from Angular and routing the request through a Play Controller for security and using Play redirect to forward the request to Solr.
This seems to be working on Chrome but not on Safari/Firefox.
Angular ajax request
var solrUrl = '/solr';
storesFactory.getAdvancedMessages = function (searchCriteria, searchType) {
var filterQuery = solrQueryComposer(searchCriteria);
$log.warn(filterQuery);
return $http({
method: 'GET',
url: solrUrl,
params: { 'q': '*',
'fq': filterQuery,
'rows': 30,
'wt': 'json'}
}).
then(function(data, status, headers, config) {
$log.debug(data.data.response.docs);
return data.data.response.docs;
},
function(error){
$log.error(error.message);
});
Play Controller
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Security;
#Security.Authenticated(Secured.class)
public class SolrController extends Controller {
private static String solrUrl = "http://whatever.com:5185/solr/select/";
private static String queryPart = "";
public static Result forward(){
queryPart = request().uri().substring(5);
System.out.println(queryPart);
return seeOther(solrUrl+queryPart);
}
}
Play Route
GET /solr controllers.SolrController.forward()
First of all, I'd like to clarify what you're doing.
Play is not forwarding anything here, it's sending a redirect to the client, asking to fetch another URL. The client will send a request, receive a redirect, and send another request.
Which means:
this controller is not "forwarding" anything. It's just tells the client to go somewhere else. ("seeOther", the name speaks for itself).
It's not secure at all. Anyone knowing solr's URL could just query it directly.
since the query is performed by the client, it may be stopped by the cross-domain security policy.
Moreover, There's a HUGE race condition waiting to happen in your code. solrUrl and queryPart are static, therefore shared by all threads, therefore shared by all clients!!
There's absolutely no reason for queryPart to be static, and actually, there's absolutely no reason for it to be in this scope. This variable should be defined in the method body.
I'd also like to point out that request().uri().substring(5) is very brittle and is going to break if you change the URL in the route file.
In return seeOther(solrUrl+queryPart), queryPart arguments keys and values should also be URLencoded.

Is this the right way to do stateless authentication per call on ServiceStack?

I have REST service requirements in which some calls require authentication and some don't. Absolutely no state is used, as the calls are all independent from one another. I have put something together which seems to work, but is this the right way to go about not using sessions?
This question is kind of related to my WCF question which is answered here.
Firstly I registered the authentication method:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new CustomCredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
}
));
I then attribute the respective calls (or service or DTO) with the Authenticate attribute:
[Authenticate]
public HelloResponse Post(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name + " with POST & Auth"};
}
I inherit from the BasicAuthProvider class which does the authentication:
public class CustomCredentialsAuthProvider : BasicAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
return userName == "dylan" && password == "abc123";
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
session.IsAuthenticated = true;
//Important: You need to save the session!
authService.SaveSession(session, new TimeSpan(0,0,10));
}
}
As you can see, I do save the session but it times out after 10 seconds. This is the part that I'm sure can potentially be done better. It seems to work nicely though.
Is there a better way of doing what I'm trying to accomplish?
Is there also any way, due to the sessionless nature of these services, to remove the Auth, AssignRoles and UnassignRoles methods?
If you wanted to keep using ServiceStack's Authentication and Session support you could just add a response filter that clears the user session after the service is executed, e.g:
this.ResponseFilters.Add((req, res, dto) => req.RemoveSession());
Basically after each request is executed it clears the session, so no record of them having authenticated exists.
Otherwise you can just skip using ServiceStack's Authentication completely and just provide your own via RequestFitlers of FilterAttributes (which is essentially what SS Auth does under the hood).