TxtyJukebox: Powering the soundtrack of your night

Picture the scene, it’s Friday night, you’ve got friends over and everyone wants to listen to some great music. The problem is everyone wants to jam to something different and you’re not thrilled to sit by your laptop all night. Enter, the TxtyJukebox.

TxtyJukebox lets you setup an event which creates you a unique number which users can text in song requests to. As TxtyJukebox receives song requests, it searches YouTube for music videos and then places the videos into your event’s queue. And then if you hook up TxtyJukebox to a TV you’ll be able to jam to videos on a big screen with big room sound. But wait, there’s more! If you have a Chromecast you can connect TxtyJukebox to your Chromecast via our app. The Chromecast app will launch from within http://jukebox.setfive.com/ so there’s nothing to download or setup.

So how does TxtyJukebox work under the hood? Well sit tight, technical details lay ahead. The webapp itself is a standard Symfony2 app along with the usual suspects - Bootstrap, Underscore, and a sprinkling of jQuery. Along with that, we’re using Twillio’s REST API to handle SMS along with a “webhook” from Twillio to the webapp to recieve messages. In addition, we’re leveraging the YouTube API to search and load videos which are then loaded into an iframe. Finally, the Chromecast app is HTML/CSS/JS powered by jQuery and underscore.

Building TxtyJukebox was a lot of fun and we’re thrilled that it’s been positively received. An awesome surprise was that Ryan over at Makeusof.com found it and incldued it in his post of How to Share Music from Multiple Devices to a Chromecast. As always, let us know if you have any questions or comments.

Spring Boot: Authentication with custom HTTP header

For the last few months we’ve been working on a Spring Boot project and one of the more challenging aspects has been wrangling Spring’s security component. For the project, we were looking to authenticate users using a custom HTTP header that contained a token generated from a third party service. There doesn’t seem to be a whole lot of concrete examples on how to set something like this up so here’s some notes from the trenches. Note: I’m still new to Spring so if any of this is inaccurate, let me know in the comments.

Concretely, what we’re looking to do is authenticate a user by passing a value in an X-Authorization HTTP header. So for example using cURL or jQuery:

:~$ curl -H "X-Authorization: $some_secret_token" http://localhost/user

$.ajax({
    url: 'http://localhost/user',
    headers: { 'X-Authorization': '$some_secret_token' }
});

In addition to insuring that the token is valid, we also want to setup Spring Security so that we can access the user’s details using “SecurityContextHolder.getContext().getAuthentication()”. So how do you do this? Turns out, you need a couple of classes to make this work:

  • An Authentication Token: You need a class that extends AbstractAuthenticationToken so that you can let Spring know about your authenticated user. The UsernamePasswordAuthenticationToken class is a pretty good starting point.
  • The Filter: You’ll need to create a filter to inspect requests that you want authenticated, grab the X-Authentication filter, confirm that it’s a valid token, and set the corresponding Authentication. Since we only want this to run once per request you can extend the OncePerRequestFilter class to set this up. You can see an example class below:

    import java.io.IOException;
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    public class DemoAuthenticationFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            
            String xAuth = request.getHeader("X-Authorization");
            
            // validate the value in xAuth
            if(isValid(xAuth) == false){
                throw new SecurityException();
            }                            
            
            // The token is 'valid' so magically get a user id from it
            Long id = getUserIdFromToken(xAuth);
            
            // Create our Authentication and let Spring know about it
            Authentication auth = new DemoAuthenticationToken(id);
            SecurityContextHolder.getContext().setAuthentication(auth);            
            
            filterChain.doFilter(request, response);
        }
    
    }
  • An Authentication Provider: The final piece is a class that extends AuthenticationProvider which handles retrieving a JPA entity from the database. By implementing an AuthenticationProvider instead of doing the database lookup in the filter, you can keep your filter framework agnostic by not having to autowire in a JPA repository. My implementation looks similar to:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.stereotype.Component;
    import com.pearson.reader.error.UnknownUserException;
    import com.pearson.reader.models.User;
    import com.pearson.reader.repositories.UserRepository;
    
    @Component
    public class DemoAuthenticationProvider implements AuthenticationProvider {
    
        // This would be a JPA repository to snag your user entities
        private final UserRepository userRepository;
        
        @Autowired
        public DemoAuthenticationProvider(UserRepository userRepository) {
            this.userRepository = userRepository;
        }    
        
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            
            DemoAuthenticationToken demoAuthentication = (DemoAuthenticationToken) authentication;        
            User user = userRepository.find(demoAuthentication.getId());
            
            if(user == null){
                throw new UnknownUserException("Could not find user with ID: " + demoAuthentication.getId());
            }
            
            return user;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return DemoAuthenticationToken.class.isAssignableFrom(authentication);
        }
    
    }

And finally, the last step is to wire this all up. You’ll need a class that extends WebSecurityConfigurerAdapter with two ovveridden configure methods to configure the filter and the authentication provider. For example, the following works at a bare minimum:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfigDemo extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private DemoAuthenticationProvider demoAuthenticationProvider;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {        
                
        http
        .authorizeRequests()
            .antMatcher("/user")
                .addFilterBefore(new DemoAuthenticationFilter(), BasicAuthenticationFilter.class)                
        ;
                        
    }
    
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {        
        auth.authenticationProvider(demoAuthenticationProvider);        
    }    
    
}

And then finally to access the authenticated user from a controller you’d do:

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) auth.getPrincipal();

Anyway, hope this helps and as mentioned above if there’s anything inaccurate feel free to post in the comments.

AngularJS: Using dynamic content with $compile

One of the more opaque concepts about AngularJS is the process that converts a chunk of HTML from a template into “Angularized” HTML which is then inserted into the DOM. During this conversions, custom directives are replaced with their corresponding HTML content, Angular directives like ng-repeat are processed, and any event handlers of interest are wired up. As it turns out, Angular’s $compile service is what’s responsible for making the magic happen. OK great, but why is this interesting or important? Because leveraging the $compile service directly lets you take dynamic content and process it to enable Angular directives and behaviors.

Since examples are always helpful, here’s an admittedly contrived one that we’ll walkthrough. Imagine that we’re building a WordPress slideshow plugin and we want to support custom themes for individual slides. So in our plugin, a user would be able to modify the HTML that displays a slide, we’d save it to the database, and then retrieve that template when we render the slides. For arguments sake, let’s assume the “default” template for the slideshow looks something like this:

<div ng-class="slide.isActive ? 'active slide' : 'slide'">
  <slide-image ng-src="{{ slide.imageSrc }}"></slide-image>
  <div class="description" ng-bind="slide.description"></div>
  <starbar config="slide.starConfig"></starbar>
</div>

As you can see, we’ve got a few directives and by default we’re displaying some description. Generally, we could set this up by creating a “slide” directive that looks something like:

angular.directive('slide', function(){
    return {
      restrict: 'E',
      scope: {slide: '='},      
      templateUrl: 'slide.html',
    };
});

Great, nothing to crazy but with this setup there’s no way to supply dynamic HTML from our database to use in the template. In order to allow a custom template you’d just need to modify the directive to look something like:

.directive('slide', function($sce, $compile){
  return {
    restrict: 'E',
    replace: true,
    scope: {slide: '='},
    template: "<div></div>",
    link: function(scope, el, attr){
      angular.element(el).html(scope["slide"].template);
      $compile(el)(scope);
    }
  };
})

And then you’d be able to use it with:

<slide slide='config'></slide>

/** Javascript **/
$scope["config"] = {
  "template": "<h3 style='color: red; font-weight: bold' ng-bind='slide.description'></h3>",
  "description": "hello world!",
};

The key difference is that in the modified directive the template is inserted into the directive’s element using “angular.element(el).html(scope[“slide”].template);“ and then finally the $compile service is invoked to process the regular HTML to get Angular magic.

Anyway, as always questions or comments welcome!

Setfive: Looking back on a summer of shenanigans

Labor day has come and gone so summer is officially over. We sat down with our intern Phil to chat about his time interning at Setfive.

Favorite Part About Interning At Setfive?

My favorite part about interning at Setfive was being introduced to so many different programming tools, and having the ability to increase my programming skill set. This summer I learned about PHP, the Symfony 2 Framework, MYSQL, I improved my JavaScript skills, learned some Angular.js, and even learned how to write unit tests. I was exposed to so many new things that everyday was fun and no two days were ever the same.

The environment here encouraged questions, and allowed me to ask and receive answers to anything I wanted to know more about. Some of the guys would even go out of their way to send me related documentation about something if they felt that they couldn’t confidently answer it themselves.

Working under the guys here was an incredible experience, I was given the freedom to make mistakes and figure out problems on my own, but at the same time was given sufficient structure to make consistent progress. It was awesome to have the comfort of knowing I had a smart, qualified person to guide me in the right direction if I ever got too stuck on any one problem.

Most important thing that you learned?

The most important skill that I learned was definitely an improved conceptual understanding of MVC, and that while sometimes using this pattern slows down your programming, in the long run it helps you create readable, modular code.

I also learned that installation is just the worst.

Most Memorable Moment?

The most memorable moment of the summer was the first time we used the Txty Jukebox in the office. It didn’t quite work the first time around, however, watching people use and get enjoyment out of something that I helped to create was something that I’ will never forget.

Where do you want to go from here?

From here I definitely want to continue building custom applications. I’ve spent the last part of the summer teaching myself objective-c, and the skills that I’ve learned here will definitely help me make the transition into developing iOS applications.

Top 5 Things To Eat

  1. Buffalo Soulja - Darwins (Only available on Thursdays)
  2. Mango Bubble Tea - Dosa Factory
  3. Steak Sammy - Orinoco
  4. Burger topped with shortrib meat – Charlies Beer Garden
  5. Chicken Pad Thai - Thelonious Monkfish
  6. Honorable Mention: Cuban Sammy - Plough and Stars

AngularJS: onLoad from an iframe directive

A couple of days ago in my journey down the AngularJS rabbit hole I ran into an interesting issue. If you have a directive that’s dynamically adding an iframe tag how can you set an onLoad handler on the iframe with access to the directive’s $scope?

Interestingly, the top StackOverflow answer on Google recommends adding a function to the window object and then setting the onLoad attribute to that function. Although it works, this approach is decidedly not “the Angular way” and would definitely become unwieldy with more than one iframe on the page. I poked around a bit and turns out there’s a better way to do this. The “trick” is that it’s possible to access a directive’s $scope from inside its link function so you can set onLoad on the iframe element from there. This post provides an overview but it’s a bit light on details so here’s a concrete example.

angular.module( 'videoPlayer')

.directive('video', function(){
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'components/video.tpl.html',    
    link: function(scope, el, attr){
      el.find("iframe")[0].onload = function(){
        scope["onIframeLoaded"]();
      };
    },
    controller: function($scope, $sce){
       
       $scope["onIframeLoaded"] = function(){
         // Do whatever you need to do after the iframe has loaded
       };
       
       $scope["embedUrl"] = $sce.trustAsResourceUrl("https://www.youtube.com/embed/dQw4w9WgXcQ");
    }
  };
})

// components/video.tpl.html
<div class="video-container">
  <iframe ng-src="{{embedUrl}}"></iframe>
</div>