Skip to content

Instantly share code, notes, and snippets.

@roblav96
Created July 22, 2016 12:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roblav96/b9ccbf146bd9994c825860114cd1e7f0 to your computer and use it in GitHub Desktop.
Save roblav96/b9ccbf146bd9994c825860114cd1e7f0 to your computer and use it in GitHub Desktop.
Robert Laverty - Angular Questionnaire
/**
*
* List three ways to communicate between modules in your Angular app. Which do you prefer and why?
*
*/
// THESE ARE NOT ORDERED FROM FAVORITE TO WORST
// I don't really have a preference to the following methods, (except factory & service) because each method has its own unique functionality.
/*=====================================
= 1. $rootScope =
=====================================*/
// It allows me to access simple variables wherever $scope is present.
// If I have a variable I'd like to access globally throughout my application, I would set it in the $rootScope during app.run():
app.run( function ( $rootScope ) {
$rootScope.data = {}
$rootScope.data.uname = null
$rootScope.data.ucompany = null
} )
// Then once the user logs in, I can set those using $scope:
$http.post( '/login', $scope.formData ).success( function ( res ) {
$scope.data.uname = res.uname // "rglaverty3464"
$scope.data.ucompany = res.ucompany // "VentureApp"
} )
// In my tool bar template, I've put:
/*
<md-button ng-click="$mdOpenMenu($event)">
<div layout="row" layout-align="center center">
<span>{{data.uname}}</span>
</div>
</md-button>
*/
// Now that "uname" is set, I can access that variable wherever $scope is present.
/*=============================================
= 2. Services/Factories =
=============================================*/
// If you look at the source code, services and factories are basically the same.
// I can still construct a service in the form of a factory like so:
app.service( 'MyService', function () {
return {
sayHello: function () {
console.log( 'hello' )
}
}
} )
// I PREFER services OVER factories because:
// - Services let us use ES6 classes
// - Services are actual constructor functions
// I use a service to set and store data. Mostly all my $http() functions are stored in a service.
// I can then dynamically load these services into my modules to maximize performance and efficiency.
// In this example, I've created a toast notification for the client when an error occurs on the server side.
// On the server, I've defined an array of objects with different errors e.g. "Email already in use.", "Five minutes passed, captcha expired.", "Your account has been locked due to too many password entry's.", etc.
// I can also store private errors for my server to log without letting the client know too much information.
// For example, the server will send:
if ( errsAry[ req.route.path ][ req.route.method ][ num ].public ) {
statusCode = 400
errz.msg = errsAry[ req.route.path ][ req.route.method ][ num ].msg
}
// and the client will dynamically create the toast based on whatever the server sends:
app.service( 'HeadersInterceptor', function ( $q, $rootScope, $errz ) {
this.responseError = function ( rej ) {
if ( rej.status == 400 ) {
$errz.toast( rej.data.msg )
} else if ( rej.status == 500 ) {
$errz.toast( "ERROR CODE: " + rej.data.num + " @ " + rej.data.method + " - " + rej.data.path )
}
return $q.reject( rej )
}
} )
// My philosophy is to never give the client and control over anything what so ever.
/*========================================
= 3. Other Modules =
========================================*/
// I like that I can dynamically inject modules into other modules.
// For example, I'll have a module for toast notifications containing controllers, services, etc.
// I would then inject this module into parts of the app that would require me to use toast notifications.
/**
*
* Discuss $scope object’s inheritance across nested controllers, and when it’s appropriate to use nested controllers.
*
*/
/*==============================
= $scope =
==============================*/
// As I discussed earlier with $rootScope, storing global variables in the $rootScope will allow you to access those variables wherever $scope is available.
// When you have nested controllers, you can access parent controllers $scope variables.
// For example:
$stateProvider.state( 'public', {
url: '/public',
abstract: true,
controller: 'PublicCtrl',
templateUrl: 'index.html',
} ).state( 'public.login', {
url: '/login',
controller: 'LoginCtrl',
templateUrl: 'login.html'
} )
// then do:
app.controller( 'PublicCtrl', [ '$scope', function ( $scope ) {
$scope.uname = "rglaverty96"
} ] )
app.controller( 'LoginCtrl', [ '$scope', function ( $scope ) {
console.log( $scope.uname ) // prints out > rglaverty96
} ] )
// Because 'LoginCtrl' is nested inside 'PublicCtrl', I can access my $scope.uname variable from within 'LoginCtrl'.
// I use nested controllers exactly how explained in that example.
// I'll put this:
$scope.href = function ( loc, parms ) {
$state.go( loc, {
id: parms || ""
} )
}
// in my 'PublicCtrl', so that I can access that function in child controllers.
/**
*
* Discuss the ideal file structure of the following admin application
*
*/
/*========================================
= Folder Structure =
========================================*/
// .
// ├── app
// │ ├── app.js
// │ ├── shared
// │ │ ├── controllers
// │ │ ├── directives
// │ │ └── services
// │ │ └── views
// │ ├── users
// │ │ ├── controllers
// │ │ │ └── UsersCtrl.js
// │ │ ├── directives
// │ │ │ └── UsersDirec.js
// │ │ ├── services
// │ │ │ └── UsersServs.js
// │ │ └── views
// │ │ ├── list-users.html
// │ │ └── edit-user.html
// │ └── companies
// │ ├── controllers
// │ │ └── CompaniesCtrl.js
// │ ├── directives
// │ │ └── CompaniesDirecs.js
// │ ├── services
// │ │ └── CompaniesServs.js
// │ └── views
// │ ├── list-copmanies.html
// │ └── edit-copmanies.html
// ├── assets
// ├── lib
// ├── test
// └── index.html
// With this folder setup, I can see everything perfectly on my sidebar in sublime text.
// This structure also works very well with other IDE's
/**
*
* Discuss JSON web tokens and how you would implement them when communicating and authenticating with an API
*
*/
/*=======================================
= JSON Web Tokens =
=======================================*/
// Let me start off by saying I'm quite knowledgeable with with OWASP top 10.
// I think JSON web tokens are great. The fundamental idea of data inside the hash is very intuitive.
// In my custom JSON web token module, I've added the fields "IP Address", "User Session Key", and "User Agent"
/*===== CLIENT ======*/
// I would require a JOSN web token on EVERY REQUEST from the client:
app.service( 'HeadersInterceptor', function ( $q, $rootScope, $timeout ) {
this.request = function ( config ) {
config.headers[ 'x-id' ] = $rootScope.data.id
config.headers[ 'x-token' ] = $rootScope.data.token
}
} )
/*===== SERVER ======*/
// Before anything, I would verify and authenticate the request user:
var tok = req.headers[ 'x-token' ]
// retrieve this users key to decrypt their data
var privateKey = forge.pki.privateKeyFromPem( forge.util.decode64( doc.crypt.privateKey ) )
try {
tok = privateKey.decrypt( forge.util.decode64( tok ), 'RSA-OAEP' )
} catch ( err ) {
return e.errz( 104, req, res, err )
}
if ( tok.length != 78 ) { // make sure token is correct length
return e.errz( 104, req, res )
}
// we do this to prevent someone snooping the traffic and 'replaying' requests
var expire = tok.substr( tok.indexOf( '.' ) + 1, tok.length ) // extract the token time stamp
var time = _.now() - expire
if ( time > 60000 ) { // greater than 1 minute, expired
return e.errz( 107, req, res )
}
var token = tok.substr( 0, tok.indexOf( '.' ) ) // get token index from the '.' like JWT do
var hashed = {}
var md = forge.md.sha1.create();
hashed.uname = md.update( doc._id ).digest().toHex();
var md = forge.md.sha1.create();
hashed.agentz = md.update( doc.sessions[ req.idz ].agent ).digest().toHex();
var md = forge.md.sha1.create();
hashed.ip = md.update( doc.sessions[ req.idz ].ip + doc.sessions[ req.idz ].family ).digest().toHex();
// use HMAC 256 algorithm
var msg = req.idz + hashed.uname + doc.sessions[ req.idz ].prime + hashed.agentz + hashed.ip
var hmac = forge.hmac.create()
hmac.start( 'sha256', doc.pass )
hmac.update( msg )
var dbToken = hmac.digest().toHex()
if ( dbToken != token ) { // compare the two hashes
return e.errz( 106, req, res ) // INVALID USER
}
return next() // VALID USER
/*===== NOTES ======*/
// If I wanted to go crazy with this, I would send back a different JWT each response.
// I built my own custom authentication system for my node projects following the JWT fundamentals.
/**
*
* Use Angular to parse this snippet onto a web page.
*
*/
/*=====================================
= ANGULAR PARSE =
=====================================*/
/*===== APP.JS ======*/
// First you need to include ngSanitize.
angular.module( 'myapp', [ 'ngSanitize' ] )
// Setup a $scope holder for the string because $http is a promise function
$scope.str = null;
// Get the string from the server
$http.get( "http://pastebin.com/raw.php?i=JX2Fw9Fq" ).success( function ( res ) { // Throws a CORS error :(
$scope.str = res.str.replace( /\n\r?/g, '<br />' )
} )
/*===== VIEW.HTML ======*/
// put the string in ng-bind-html
// <p ng-bind-html="str"></p>
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment