1
0
Fork 0
mirror of https://github.com/mmumshad/ansible-playable.git synced 2025-03-09 23:38:54 +00:00

Initial Commit

This commit is contained in:
Mumshad Mannambeth 2017-06-07 13:36:44 -04:00
commit c92f737237
273 changed files with 16964 additions and 0 deletions

View file

@ -0,0 +1,34 @@
'use strict';
import angular from 'angular';
import constants from '../../app/app.constants';
import util from '../util/util.module';
import ngCookies from 'angular-cookies';
import {
authInterceptor
} from './interceptor.service';
import {
routerDecorator
} from './router.decorator';
import {
AuthService
} from './auth.service';
import {
UserResource
} from './user.service';
import uiRouter from 'angular-ui-router';
function addInterceptor($httpProvider) {
'ngInject';
$httpProvider.interceptors.push('authInterceptor');
}
export default angular.module('app2App.auth', [constants, util, ngCookies, uiRouter])
.factory('authInterceptor', authInterceptor)
.run(routerDecorator)
.factory('Auth', AuthService)
.factory('User', UserResource)
.config(['$httpProvider', addInterceptor])
.name;

View file

@ -0,0 +1,226 @@
'use strict';
import * as _ from 'lodash';
class _User {
_id = '';
name = '';
email = '';
role = '';
$promise = undefined;
}
export function AuthService($location, $http, $cookies, $q, appConfig, Util, User) {
'ngInject';
var safeCb = Util.safeCb;
var currentUser = new _User();
var userRoles = appConfig.userRoles || [];
/**
* Check if userRole is >= role
* @param {String} userRole - role of current user
* @param {String} role - role to check against
*/
var hasRole = function(userRole, role) {
return userRoles.indexOf(userRole) >= userRoles.indexOf(role);
};
if($cookies.get('token') && $location.path() !== '/logout') {
currentUser = User.get();
}
var Auth = {
/**
* Authenticate user and save token
*
* @param {Object} user - login info
* @param {Function} callback - function(error, user)
* @return {Promise}
*/
login({
email,
password
}, callback) {
return $http.post('/auth/local', {
email,
password
})
.then(res => {
$cookies.put('token', res.data.token);
currentUser = User.get();
return currentUser.$promise;
})
.then(user => {
safeCb(callback)(null, user);
return user;
})
.catch(err => {
Auth.logout();
safeCb(callback)(err.data);
return $q.reject(err.data);
});
},
/**
* Delete access token and user info
*/
logout() {
$cookies.remove('token');
currentUser = new _User();
},
/**
* Create a new user
*
* @param {Object} user - user info
* @param {Function} callback - function(error, user)
* @return {Promise}
*/
createUser(user, callback) {
return User.save(user, function(data) {
$cookies.put('token', data.token);
currentUser = User.get();
return safeCb(callback)(null, user);
}, function(err) {
Auth.logout();
return safeCb(callback)(err);
})
.$promise;
},
/**
* Change password
*
* @param {String} oldPassword
* @param {String} newPassword
* @param {Function} callback - function(error, user)
* @return {Promise}
*/
changePassword(oldPassword, newPassword, callback) {
return User.changePassword({
id: currentUser._id
}, {
oldPassword,
newPassword
}, function() {
return safeCb(callback)(null);
}, function(err) {
return safeCb(callback)(err);
})
.$promise;
},
/**
* Gets all available info on a user
*
* @param {Function} [callback] - function(user)
* @return {Promise}
*/
getCurrentUser(callback) {
var value = _.get(currentUser, '$promise') ? currentUser.$promise : currentUser;
return $q.when(value)
.then(user => {
safeCb(callback)(user);
return user;
}, () => {
safeCb(callback)({});
return {};
});
},
/**
* Gets all available info on a user
*
* @return {Object}
*/
getCurrentUserSync() {
return currentUser;
},
/**
* Check if a user is logged in
*
* @param {Function} [callback] - function(is)
* @return {Promise}
*/
isLoggedIn(callback) {
return Auth.getCurrentUser(undefined)
.then(user => {
let is = _.get(user, 'role');
safeCb(callback)(is);
return is;
});
},
/**
* Check if a user is logged in
*
* @return {Bool}
*/
isLoggedInSync() {
return !!_.get(currentUser, 'role');
},
/**
* Check if a user has a specified role or higher
*
* @param {String} role - the role to check against
* @param {Function} [callback] - function(has)
* @return {Promise}
*/
hasRole(role, callback) {
return Auth.getCurrentUser(undefined)
.then(user => {
let has = hasRole(_.get(user, 'role'), role);
safeCb(callback)(has);
return has;
});
},
/**
* Check if a user has a specified role or higher
*
* @param {String} role - the role to check against
* @return {Bool}
*/
hasRoleSync(role) {
return hasRole(_.get(currentUser, 'role'), role);
},
/**
* Check if a user is an admin
* (synchronous|asynchronous)
*
* @param {Function|*} callback - optional, function(is)
* @return {Bool|Promise}
*/
isAdmin(...args) {
return Auth.hasRole(Reflect.apply([].concat, ['admin'], args));
},
/**
* Check if a user is an admin
*
* @return {Bool}
*/
isAdminSync() {
// eslint-disable-next-line no-sync
return Auth.hasRoleSync('admin');
},
/**
* Get auth token
*
* @return {String} - a token string used for authenticating
*/
getToken() {
return $cookies.get('token');
}
};
return Auth;
}

View file

@ -0,0 +1,28 @@
'use strict';
export function authInterceptor($rootScope, $q, $cookies, $injector, Util) {
'ngInject';
var state;
return {
// Add authorization token to headers
request(config) {
config.headers = config.headers || {};
if($cookies.get('token') && Util.isSameOrigin(config.url)) {
config.headers.Authorization = `Bearer ${$cookies.get('token')}`;
}
return config;
},
// Intercept 401s and redirect you to login
responseError(response) {
if(response.status === 401) {
(state || (state = $injector.get('$state')))
.go('login');
// remove any stale tokens
$cookies.remove('token');
}
return $q.reject(response);
}
};
}

View file

@ -0,0 +1,38 @@
'use strict';
export function routerDecorator($rootScope, $state, Auth) {
'ngInject';
// Redirect to login if route requires auth and the user is not logged in, or doesn't have required role
$rootScope.$on('$stateChangeStart', function(event, next) {
if(!next.authenticate) {
return;
}
if(typeof next.authenticate === 'string') {
Auth.hasRole(next.authenticate)
.then(has => {
if(has) {
return;
}
event.preventDefault();
return Auth.isLoggedIn()
.then(is => {
$state.go(is ? 'main' : 'login');
});
});
} else {
Auth.isLoggedIn()
.then(is => {
if(is) {
return;
}
event.preventDefault();
$state.go('login');
});
}
});
}

View file

@ -0,0 +1,22 @@
'use strict';
export function UserResource($resource) {
'ngInject';
return $resource('/api/users/:id/:controller', {
id: '@_id'
}, {
changePassword: {
method: 'PUT',
params: {
controller: 'password'
}
},
get: {
method: 'GET',
params: {
id: 'me'
}
}
});
}

View file

@ -0,0 +1,10 @@
import angular from 'angular';
export class FooterComponent {}
export default angular.module('directives.footer', [])
.component('footer', {
template: require('./footer.html'),
controller: FooterComponent
})
.name;

View file

@ -0,0 +1,6 @@
footer.footer {
text-align: center;
padding: 30px 0;
margin-top: 70px;
border-top: 1px solid #E5E5E5;
}

View file

@ -0,0 +1,8 @@
<div class="container">
<p>Angular Fullstack v4.2.2 |
<a href="http://angular-fullstack.github.io/">Documentation</a> |
<a href="https://gitter.im/DaftMonk/generator-angular-fullstack">Chat on Gitter</a> |
<a href="https://github.com/angular-fullstack/generator-angular-fullstack/issues?state=open">Issues</a> |
<a href="https://opencollective.com/angular-fullstack">Donate to our Open Collective</a>
</p>
</div>

View file

@ -0,0 +1,23 @@
.modal-primary .modal-header,
.modal-info .modal-header,
.modal-success .modal-header,
.modal-warning .modal-header,
.modal-danger .modal-header {
color: #fff;
border-radius: 5px 5px 0 0;
}
.modal-primary .modal-header {
background: #428bca;
}
.modal-info .modal-header {
background: #5bc0de;
}
.modal-success .modal-header {
background: #5cb85c;
}
.modal-warning .modal-header {
background: #f0ad4e;
}
.modal-danger .modal-header {
background: #d9534f;
}

View file

@ -0,0 +1,11 @@
<div class="modal-header">
<button ng-if="modal.dismissable" type="button" ng-click="$dismiss()" class="close">&times;</button>
<h4 ng-if="modal.title" ng-bind="modal.title" class="modal-title"></h4>
</div>
<div class="modal-body">
<p ng-if="modal.text" ng-bind="modal.text"></p>
<div ng-if="modal.html" ng-bind-html="modal.html"></div>
</div>
<div class="modal-footer">
<button ng-repeat="button in modal.buttons" ng-class="button.classes" ng-click="button.click($event)" ng-bind="button.text" class="btn"></button>
</div>

View file

@ -0,0 +1,78 @@
'use strict';
import angular from 'angular';
export function Modal($rootScope, $uibModal) {
/**
* Opens a modal
* @param {Object} scope - an object to be merged with modal's scope
* @param {String} modalClass - (optional) class(es) to be applied to the modal
* @return {Object} - the instance $uibModal.open() returns
*/
function openModal(scope = {}, modalClass = 'modal-default') {
var modalScope = $rootScope.$new();
angular.extend(modalScope, scope);
return $uibModal.open({
template: require('./modal.html'),
windowClass: modalClass,
scope: modalScope
});
}
// Public API here
return {
/* Confirmation modals */
confirm: {
/**
* Create a function to open a delete confirmation modal (ex. ng-click='myModalFn(name, arg1, arg2...)')
* @param {Function} del - callback, ran when delete is confirmed
* @return {Function} - the function to open the modal (ex. myModalFn)
*/
delete(del = angular.noop) {
/**
* Open a delete confirmation modal
* @param {String} name - name or info to show on modal
* @param {All} - any additional args are passed straight to del callback
*/
return function(...args) {
var slicedArgs = Reflect.apply(Array.prototype.slice, args);
var name = slicedArgs.shift();
var deleteModal;
deleteModal = openModal({
modal: {
dismissable: true,
title: 'Confirm Delete',
html: `<p>Are you sure you want to delete <strong>${name}</strong> ?</p>`,
buttons: [{
classes: 'btn-danger',
text: 'Delete',
click(e) {
deleteModal.close(e);
}
}, {
classes: 'btn-default',
text: 'Cancel',
click(e) {
deleteModal.dismiss(e);
}
}]
}
}, 'modal-danger');
deleteModal.result.then(function(event) {
Reflect.apply(del, event, slicedArgs);
});
};
}
}
};
}
export default angular.module('app2App.Modal', [])
.factory('Modal', Modal)
.name;

View file

@ -0,0 +1,17 @@
'use strict';
import angular from 'angular';
/**
* Removes server error when user updates input
*/
angular.module('app2App')
.directive('mongooseError', function() {
return {
restrict: 'A',
require: 'ngModel',
link(scope, element, attrs, ngModel) {
element.on('keydown', () => ngModel.$setValidity('mongoose', true));
}
};
});

View file

@ -0,0 +1,41 @@
'use strict';
/* eslint no-sync: 0 */
import angular from 'angular';
export class NavbarComponent {
menu = [{
'title': 'Home',
'state': 'main'
},{
'title': 'Projects',
'state': 'project'
},{
'title': 'Designer',
'state': 'designer'
},{
'title': 'Runs',
'state': 'runs'
},{
'title': 'Modules',
'state': 'custom_modules'
}];
isCollapsed = true;
constructor(Auth) {
'ngInject';
this.isLoggedIn = Auth.isLoggedInSync;
this.isAdmin = Auth.isAdminSync;
this.getCurrentUser = Auth.getCurrentUserSync;
}
}
export default angular.module('directives.navbar', [])
.component('navbar', {
template: require('./navbar.html'),
controller: NavbarComponent
})
.name;

View file

@ -0,0 +1,29 @@
<div class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<a href="/" class="navbar-brand"><small><span style="font-size:25px;font-family:'ExpletusSans-Regular'">play<span style="font-size:35px;">A</span>ble</span></small></a>
<button class="navbar-toggle" type="button" ng-click="$ctrl.isCollapsed = !$ctrl.isCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div uib-collapse="$ctrl.isCollapsed" class="navbar-collapse collapse" id="navbar-main">
<ul class="nav navbar-nav">
<li ng-repeat="item in $ctrl.menu" ui-sref-active="active">
<a ui-sref="{{item.state}}">{{item.title}}</a>
</li>
<li ng-show="$ctrl.isAdmin()" ui-sref-active="active"><a ui-sref="admin">Admin</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-hide="$ctrl.isLoggedIn()" ui-sref-active="active"><a ui-sref="signup">Sign up</a></li>
<li ng-hide="$ctrl.isLoggedIn()" ui-sref-active="active"><a ui-sref="login">Login</a></li>
<li ng-show="$ctrl.isLoggedIn()"><p class="navbar-text">Hello {{ $ctrl.getCurrentUser().name }}</p> </li>
<li ng-show="$ctrl.isLoggedIn()" ui-sref-active="active"><a ui-sref="settings"><span class="glyphicon glyphicon-cog"></span></a></li>
<li ng-show="$ctrl.isLoggedIn()"><a ui-sref="logout">Logout</a></li>
</ul>
</div>
</div>
</div>

View file

@ -0,0 +1,25 @@
'use strict';
import angular from 'angular';
export function OauthButtonsController($window) {
'ngInject';
this.loginOauth = function(provider) {
$window.location.href = `/auth/${provider}`;
};
}
export default angular.module('app2App.oauthButtons', [])
.directive('oauthButtons', function() {
return {
template: require('./oauth-buttons.html'),
restrict: 'EA',
controller: OauthButtonsController,
controllerAs: 'OauthButtons',
scope: {
classes: '@'
}
};
})
.name;

View file

@ -0,0 +1,32 @@
'use strict';
import {
OauthButtonsController
} from './index';
describe('Controller: OauthButtonsController', function() {
var controller, $window;
beforeEach(() => {
angular.module('test', [])
.controller('OauthButtonsController', OauthButtonsController);
});
// load the controller's module
beforeEach(angular.mock.module('test'));
// Initialize the controller and a mock $window
beforeEach(inject(function($controller) {
$window = {
location: {}
};
controller = $controller('OauthButtonsController', {
$window
});
}));
it('should attach loginOauth', function() {
expect(controller.loginOauth)
.to.be.a('function');
});
});

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,59 @@
'use strict';
const $ = require('sprint-js');
import OauthButtons from './index';
describe('Directive: oauthButtons', function() {
// load the directive's module and view
beforeEach(angular.mock.module(OauthButtons));
// beforeEach(angular.mock.module('components/oauth-buttons/oauth-buttons.html'));
var element, parentScope, elementScope;
var compileDirective = function(template) {
inject(function($compile) {
element = angular.element(template);
element = $compile(element)(parentScope);
parentScope.$digest();
elementScope = element.isolateScope();
});
};
beforeEach(inject(function($rootScope) {
parentScope = $rootScope.$new();
}));
it('should contain anchor buttons', function() {
compileDirective('<oauth-buttons></oauth-buttons>');
expect($(element[0])
.find('a.btn.btn-social')
.length)
.to.be.at.least(1);
});
it('should evaluate and bind the classes attribute to scope.classes', function() {
parentScope.scopedClass = 'scopedClass1';
compileDirective('<oauth-buttons classes="testClass1 {{scopedClass}}"></oauth-buttons>');
expect(elementScope.classes)
.to.equal('testClass1 scopedClass1');
});
it('should bind scope.classes to class names on the anchor buttons', function() {
compileDirective('<oauth-buttons></oauth-buttons>');
// Add classes
elementScope.classes = 'testClass1 testClass2';
elementScope.$digest();
expect($(element[0])
.find('a.btn.btn-social.testClass1.testClass2')
.length)
.to.be.at.least(1);
// Remove classes
elementScope.classes = '';
elementScope.$digest();
expect($(element[0])
.find('a.btn.btn-social.testClass1.testClass2')
.length)
.to.equal(0);
});
});

View file

@ -0,0 +1,9 @@
<a ng-class="classes" ng-click="OauthButtons.loginOauth('facebook')" class="btn btn-social btn-facebook">
<i class="fa fa-facebook"></i>
Connect with Facebook
</a>
<a ng-class="classes" ng-click="OauthButtons.loginOauth('google')" class="btn btn-social btn-google">
<i class="fa fa-google-plus"></i>
Connect with Google+
</a>

View file

@ -0,0 +1,38 @@
'use strict';
const angular = require('angular');
angular.module('stateMock', []);
angular.module('stateMock')
.service('$state', function($q) {
this.expectedTransitions = [];
this.transitionTo = function(stateName) {
if(this.expectedTransitions.length > 0) {
var expectedState = this.expectedTransitions.shift();
if(expectedState !== stateName) {
throw Error(`Expected transition to state: ${expectedState
} but transitioned to ${stateName}`);
}
} else {
throw Error(`No more transitions were expected! Tried to transition to ${stateName}`);
}
console.log(`Mock transition to: ${stateName}`);
var deferred = $q.defer();
var promise = deferred.promise;
deferred.resolve();
return promise;
};
this.go = this.transitionTo;
this.expectTransitionTo = function(stateName) {
this.expectedTransitions.push(stateName);
};
this.ensureAllTransitionsHappened = function() {
if(this.expectedTransitions.length > 0) {
throw Error('Not all transitions happened!');
}
};
});

View file

@ -0,0 +1,10 @@
'use strict';
import angular from 'angular';
import {
UtilService
} from './util.service';
export default angular.module('app2App.util', [])
.factory('Util', UtilService)
.name;

View file

@ -0,0 +1,68 @@
'use strict';
import angular from 'angular';
/**
* The Util service is for thin, globally reusable, utility functions
*/
export function UtilService($window) {
'ngInject';
var Util = {
/**
* Return a callback or noop function
*
* @param {Function|*} cb - a 'potential' function
* @return {Function}
*/
safeCb(cb) {
return angular.isFunction(cb) ? cb : angular.noop;
},
/**
* Parse a given url with the use of an anchor element
*
* @param {String} url - the url to parse
* @return {Object} - the parsed url, anchor element
*/
urlParse(url) {
var a = document.createElement('a');
a.href = url;
// Special treatment for IE, see http://stackoverflow.com/a/13405933 for details
if(a.host === '') {
a.href = a.href;
}
return a;
},
/**
* Test whether or not a given url is same origin
*
* @param {String} url - url to test
* @param {String|String[]} [origins] - additional origins to test against
* @return {Boolean} - true if url is same origin
*/
isSameOrigin(url, origins) {
url = Util.urlParse(url);
origins = origins && [].concat(origins) || [];
origins = origins.map(Util.urlParse);
origins.push($window.location);
origins = origins.filter(function(o) {
let hostnameCheck = url.hostname === o.hostname;
let protocolCheck = url.protocol === o.protocol;
// 2nd part of the special treatment for IE fix (see above):
// This part is when using well-known ports 80 or 443 with IE,
// when $window.location.port==='' instead of the real port number.
// Probably the same cause as this IE bug: https://goo.gl/J9hRta
let portCheck = url.port === o.port || o.port === '' && (url.port === '80' || url.port
=== '443');
return hostnameCheck && protocolCheck && portCheck;
});
return origins.length >= 1;
}
};
return Util;
}