diff --git a/.bowerrc b/.bowerrc
new file mode 100644
index 0000000..69fad35
--- /dev/null
+++ b/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "bower_components"
+}
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c2cdfb8
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+
+[*]
+
+# Change these settings to your own preference
+indent_style = space
+indent_size = 2
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2125666
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a22a458
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+node_modules
+dist
+.tmp
+.sass-cache
+bower_components
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..e55fc99
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+ossu-client
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..72abef0
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..79278ea
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/ossu-client.iml b/.idea/ossu-client.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/ossu-client.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..73ad098
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1458643609896
+
+ 1458643609896
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..d1fb2f0
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,22 @@
+{
+ "bitwise": true,
+ "browser": true,
+ "camelcase": true,
+ "curly": true,
+ "eqeqeq": true,
+ "esnext": true,
+ "immed": true,
+ "indent": 2,
+ "latedef": "nofunc",
+ "newcap": true,
+ "noarg": true,
+ "node": true,
+ "quotmark": "single",
+ "strict": true,
+ "undef": true,
+ "unused": true,
+ "globals": {
+ "angular": false,
+ "firebase": false
+ }
+}
diff --git a/.yo-rc.json b/.yo-rc.json
new file mode 100644
index 0000000..6589676
--- /dev/null
+++ b/.yo-rc.json
@@ -0,0 +1,11 @@
+{
+ "generator-karma": {
+ "base-path": "../",
+ "frameworks": "jasmine",
+ "browsers": "PhantomJS",
+ "app-files": "app/scripts/**/*.js",
+ "files-comments": "bower:js,endbower",
+ "bower-components-path": "bower_components",
+ "test-files": "test/mock/**/*.js,test/spec/**/*.js"
+ }
+}
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..e57e653
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,480 @@
+// Generated on 2016-03-22 using generator-angularfire 1.0.0
+'use strict';
+
+// # Globbing
+// for performance reasons we're only matching one level down:
+// 'test/spec/{,*/}*.js'
+// use this if you want to recursively match all subfolders:
+// 'test/spec/**/*.js'
+
+module.exports = function (grunt) {
+
+ // Load grunt tasks automatically
+ require('load-grunt-tasks')(grunt);
+
+ // Time how long tasks take. Can help when optimizing build times
+ require('time-grunt')(grunt);
+
+ // Configurable paths for the application
+ var appConfig = {
+ app: require('./bower.json').appPath || 'app',
+ dist: 'dist'
+ };
+
+ // Define the configuration for all the tasks
+ grunt.initConfig({
+
+ // Project settings
+ yeoman: appConfig,
+
+ // Watches files for changes and runs tasks based on the changed files
+ watch: {
+ bower: {
+ files: ['bower.json'],
+ tasks: ['wiredep']
+ },
+ js: {
+ files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
+ tasks: ['newer:jshint:all'],
+ options: {
+ livereload: '<%= connect.options.livereload %>'
+ }
+ },
+ jsTest: {
+ files: ['test/spec/{,*/}*.js'],
+ tasks: ['newer:jshint:test', 'karma']
+ },
+ compass: {
+ files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
+ tasks: ['compass:server', 'autoprefixer']
+ },
+ gruntfile: {
+ files: ['Gruntfile.js']
+ },
+ livereload: {
+ options: {
+ livereload: '<%= connect.options.livereload %>'
+ },
+ files: [
+ '<%= yeoman.app %>/{,*/}*.html',
+ '.tmp/styles/{,*/}*.css',
+ '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
+ ]
+ }
+ },
+
+ // The actual grunt server settings
+ connect: {
+ options: {
+ port: 9000,
+ // Change this to '0.0.0.0' to access the server from outside.
+ hostname: 'localhost',
+ livereload: 35729
+ },
+ livereload: {
+ options: {
+ open: true,
+ middleware: function (connect) {
+ return [
+ connect.static('.tmp'),
+ connect().use(
+ '/bower_components',
+ connect.static('./bower_components')
+ ),
+ connect().use(
+ '/app/styles',
+ connect.static('./app/styles')
+ ),
+ connect.static(appConfig.app)
+ ];
+ }
+ }
+ },
+ test: {
+ options: {
+ port: 9001,
+ middleware: function (connect) {
+ return [
+ connect.static('.tmp'),
+ connect.static('test'),
+ connect().use(
+ '/bower_components',
+ connect.static('./bower_components')
+ ),
+ connect.static(appConfig.app)
+ ];
+ }
+ }
+ },
+ dist: {
+ options: {
+ open: true,
+ base: '<%= yeoman.dist %>'
+ }
+ }
+ },
+
+ // Make sure code styles are up to par and there are no obvious mistakes
+ jshint: {
+ options: {
+ jshintrc: '.jshintrc',
+ reporter: require('jshint-stylish')
+ },
+ all: {
+ src: [
+ 'Gruntfile.js',
+ '<%= yeoman.app %>/scripts/{,*/}*.js'
+ ]
+ },
+ test: {
+ options: {
+ jshintrc: 'test/.jshintrc'
+ },
+ src: ['test/spec/{,*/}*.js']
+ }
+ },
+
+ // Empties folders to start fresh
+ clean: {
+ dist: {
+ files: [{
+ dot: true,
+ src: [
+ '.tmp',
+ '<%= yeoman.dist %>/{,*/}*',
+ '!<%= yeoman.dist %>/.git{,*/}*'
+ ]
+ }]
+ },
+ server: '.tmp'
+ },
+
+ // Add vendor prefixed styles
+ autoprefixer: {
+ options: {
+ browsers: ['last 1 version']
+ },
+ server: {
+ options: {
+ map: true,
+ },
+ files: [{
+ expand: true,
+ cwd: '.tmp/styles/',
+ src: '{,*/}*.css',
+ dest: '.tmp/styles/'
+ }]
+ },
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/styles/',
+ src: '{,*/}*.css',
+ dest: '.tmp/styles/'
+ }]
+ }
+ },
+
+ // Automatically inject Bower components into the app
+ wiredep: {
+ options: {
+ cwd: ''
+ },
+ app: {
+ src: ['<%= yeoman.app %>/index.html'],
+ ignorePath: /\.\.\//
+ },
+ test: {
+ devDependencies: true,
+ src: '<%= karma.unit.configFile %>',
+ ignorePath: /\.\.\//,
+ fileTypes:{
+ js: {
+ block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
+ detect: {
+ js: /'(.*\.js)'/gi
+ },
+ replace: {
+ js: '\'{{filePath}}\','
+ }
+ }
+ }
+ },
+ sass: {
+ src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
+ ignorePath: /(\.\.\/){1,2}bower_components\//
+ }
+ },
+
+ // Compiles Sass to CSS and generates necessary files if requested
+ compass: {
+ options: {
+ sassDir: '<%= yeoman.app %>/styles',
+ cssDir: '.tmp/styles',
+ generatedImagesDir: '.tmp/images/generated',
+ imagesDir: '<%= yeoman.app %>/images',
+ javascriptsDir: '<%= yeoman.app %>/scripts',
+ fontsDir: '<%= yeoman.app %>/styles/fonts',
+ importPath: './bower_components',
+ httpImagesPath: '/images',
+ httpGeneratedImagesPath: '/images/generated',
+ httpFontsPath: '/styles/fonts',
+ relativeAssets: false,
+ assetCacheBuster: false,
+ raw: 'Sass::Script::Number.precision = 10\n'
+ },
+ dist: {
+ options: {
+ generatedImagesDir: '<%= yeoman.dist %>/images/generated'
+ }
+ },
+ server: {
+ options: {
+ sourcemap: true
+ }
+ }
+ },
+
+ // Renames files for browser caching purposes
+ filerev: {
+ dist: {
+ src: [
+ '<%= yeoman.dist %>/scripts/{,*/}*.js',
+ '<%= yeoman.dist %>/styles/{,*/}*.css',
+ '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
+ '<%= yeoman.dist %>/styles/fonts/*'
+ ]
+ }
+ },
+
+ // Reads HTML for usemin blocks to enable smart builds that automatically
+ // concat, minify and revision files. Creates configurations in memory so
+ // additional tasks can operate on them
+ useminPrepare: {
+ html: '<%= yeoman.app %>/index.html',
+ options: {
+ dest: '<%= yeoman.dist %>',
+ flow: {
+ html: {
+ steps: {
+ js: ['concat', 'uglifyjs'],
+ css: ['cssmin']
+ },
+ post: {}
+ }
+ }
+ }
+ },
+
+ // Performs rewrites based on filerev and the useminPrepare configuration
+ usemin: {
+ html: ['<%= yeoman.dist %>/{,*/}*.html'],
+ css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
+ options: {
+ assetsDirs: [
+ '<%= yeoman.dist %>',
+ '<%= yeoman.dist %>/images',
+ '<%= yeoman.dist %>/styles'
+ ]
+ }
+ },
+
+ // The following *-min tasks will produce minified files in the dist folder
+ // By default, your `index.html`'s will take care of
+ // minification. These next options are pre-configured if you do not wish
+ // to use the Usemin blocks.
+ // cssmin: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/styles/main.css': [
+ // '.tmp/styles/{,*/}*.css'
+ // ]
+ // }
+ // }
+ // },
+ // uglify: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/scripts/scripts.js': [
+ // '<%= yeoman.dist %>/scripts/scripts.js'
+ // ]
+ // }
+ // }
+ // },
+ // concat: {
+ // dist: {}
+ // },
+
+ imagemin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.{png,jpg,jpeg,gif}',
+ dest: '<%= yeoman.dist %>/images'
+ }]
+ }
+ },
+
+ svgmin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.svg',
+ dest: '<%= yeoman.dist %>/images'
+ }]
+ }
+ },
+
+ htmlmin: {
+ dist: {
+ options: {
+ collapseWhitespace: true,
+ conservativeCollapse: true,
+ collapseBooleanAttributes: true,
+ removeCommentsFromCDATA: true,
+ removeOptionalTags: true
+ },
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.dist %>',
+ src: ['*.html', 'views/{,*/}*.html'],
+ dest: '<%= yeoman.dist %>'
+ }]
+ }
+ },
+
+ // ng-annotate tries to make the code safe for minification automatically
+ // by using the Angular long form for dependency injection.
+ ngAnnotate: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/concat/scripts',
+ src: '*.js',
+ dest: '.tmp/concat/scripts'
+ }]
+ }
+ },
+
+ // Replace Google CDN references
+ cdnify: {
+ dist: {
+ html: ['<%= yeoman.dist %>/*.html']
+ }
+ },
+
+ // Copies remaining files to places other tasks can use
+ copy: {
+ dist: {
+ files: [{
+ expand: true,
+ dot: true,
+ cwd: '<%= yeoman.app %>',
+ dest: '<%= yeoman.dist %>',
+ src: [
+ '*.{ico,png,txt}',
+ '.htaccess',
+ '*.html',
+ 'views/{,*/}*.html',
+ 'images/{,*/}*.{webp}',
+ 'styles/fonts/{,*/}*.*'
+ ]
+ }, {
+ expand: true,
+ cwd: '.tmp/images',
+ dest: '<%= yeoman.dist %>/images',
+ src: ['generated/*']
+ }, {
+ expand: true,
+ cwd: '.',
+ src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
+ dest: '<%= yeoman.dist %>'
+ }]
+ },
+ styles: {
+ expand: true,
+ cwd: '<%= yeoman.app %>/styles',
+ dest: '.tmp/styles/',
+ src: '{,*/}*.css'
+ }
+ },
+
+ // Run some tasks in parallel to speed up the build process
+ concurrent: {
+ server: [
+ 'compass:server'
+ ],
+ test: [
+ 'compass'
+ ],
+ dist: [
+ 'compass:dist',
+ 'imagemin',
+ 'svgmin'
+ ]
+ },
+
+ // Test settings
+ karma: {
+ unit: {
+ configFile: 'test/karma.conf.js',
+ singleRun: true
+ }
+ }
+ });
+
+
+ grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
+ if (target === 'dist') {
+ return grunt.task.run(['build', 'connect:dist:keepalive']);
+ }
+
+ grunt.task.run([
+ 'clean:server',
+ 'wiredep',
+ 'concurrent:server',
+ 'autoprefixer:server',
+ 'connect:livereload',
+ 'watch'
+ ]);
+ });
+
+ grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
+ grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
+ grunt.task.run(['serve:' + target]);
+ });
+
+ grunt.registerTask('test', [
+ 'clean:server',
+ 'wiredep',
+ 'concurrent:test',
+ 'autoprefixer',
+ 'connect:test',
+ 'karma'
+ ]);
+
+ grunt.registerTask('build', [
+ 'clean:dist',
+ 'wiredep',
+ 'useminPrepare',
+ 'concurrent:dist',
+ 'autoprefixer',
+ 'concat',
+ 'ngAnnotate',
+ 'copy:dist',
+ 'cdnify',
+ 'cssmin',
+ 'uglify',
+ 'filerev',
+ 'usemin',
+ 'htmlmin'
+ ]);
+
+ grunt.registerTask('default', [
+ 'newer:jshint',
+ 'test',
+ 'build'
+ ]);
+};
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..90208cd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# ossu-client
+
+This project is generated with [yo angular generator](https://github.com/yeoman/generator-angular)
+version 1.0.0.
+
+## Build & development
+
+Run `grunt` for building and `grunt serve` for preview.
+
+## Testing
+
+Running `grunt test` will run the unit tests with karma.
diff --git a/app/.buildignore b/app/.buildignore
new file mode 100644
index 0000000..fc98b8e
--- /dev/null
+++ b/app/.buildignore
@@ -0,0 +1 @@
+*.coffee
\ No newline at end of file
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 0000000..cb84cb9
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1,543 @@
+# Apache Configuration File
+
+# (!) Using `.htaccess` files slows down Apache, therefore, if you have access
+# to the main server config file (usually called `httpd.conf`), you should add
+# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
+
+# ##############################################################################
+# # CROSS-ORIGIN RESOURCE SHARING (CORS) #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Cross-domain AJAX requests |
+# ------------------------------------------------------------------------------
+
+# Enable cross-origin AJAX requests.
+# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
+# http://enable-cors.org/
+
+#
+# Header set Access-Control-Allow-Origin "*"
+#
+
+# ------------------------------------------------------------------------------
+# | CORS-enabled images |
+# ------------------------------------------------------------------------------
+
+# Send the CORS header for images when browsers request it.
+# https://developer.mozilla.org/en/CORS_Enabled_Image
+# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
+# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
+
+
+
+
+ SetEnvIf Origin ":" IS_CORS
+ Header set Access-Control-Allow-Origin "*" env=IS_CORS
+
+
+
+
+# ------------------------------------------------------------------------------
+# | Web fonts access |
+# ------------------------------------------------------------------------------
+
+# Allow access from all domains for web fonts
+
+
+
+ Header set Access-Control-Allow-Origin "*"
+
+
+
+
+# ##############################################################################
+# # ERRORS #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | 404 error prevention for non-existing redirected folders |
+# ------------------------------------------------------------------------------
+
+# Prevent Apache from returning a 404 error for a rewrite if a directory
+# with the same name does not exist.
+# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
+# http://www.webmasterworld.com/apache/3808792.htm
+
+Options -MultiViews
+
+# ------------------------------------------------------------------------------
+# | Custom error messages / pages |
+# ------------------------------------------------------------------------------
+
+# You can customize what Apache returns to the client in case of an error (see
+# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
+
+ErrorDocument 404 /404.html
+
+
+# ##############################################################################
+# # INTERNET EXPLORER #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Better website experience |
+# ------------------------------------------------------------------------------
+
+# Force IE to render pages in the highest available mode in the various
+# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
+
+
+ Header set X-UA-Compatible "IE=edge"
+ # `mod_headers` can't match based on the content-type, however, we only
+ # want to send this header for HTML pages and not for the other resources
+
+ Header unset X-UA-Compatible
+
+
+
+# ------------------------------------------------------------------------------
+# | Cookie setting from iframes |
+# ------------------------------------------------------------------------------
+
+# Allow cookies to be set from iframes in IE.
+
+#
+# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
+#
+
+# ------------------------------------------------------------------------------
+# | Screen flicker |
+# ------------------------------------------------------------------------------
+
+# Stop screen flicker in IE on CSS rollovers (this only works in
+# combination with the `ExpiresByType` directives for images from below).
+
+# BrowserMatch "MSIE" brokenvary=1
+# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
+# BrowserMatch "Opera" !brokenvary
+# SetEnvIf brokenvary 1 force-no-vary
+
+
+# ##############################################################################
+# # MIME TYPES AND ENCODING #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Proper MIME types for all files |
+# ------------------------------------------------------------------------------
+
+
+
+ # Audio
+ AddType audio/mp4 m4a f4a f4b
+ AddType audio/ogg oga ogg
+
+ # JavaScript
+ # Normalize to standard type (it's sniffed in IE anyways):
+ # http://tools.ietf.org/html/rfc4329#section-7.2
+ AddType application/javascript js jsonp
+ AddType application/json json
+
+ # Video
+ AddType video/mp4 mp4 m4v f4v f4p
+ AddType video/ogg ogv
+ AddType video/webm webm
+ AddType video/x-flv flv
+
+ # Web fonts
+ AddType application/font-woff woff
+ AddType application/vnd.ms-fontobject eot
+
+ # Browsers usually ignore the font MIME types and sniff the content,
+ # however, Chrome shows a warning if other MIME types are used for the
+ # following fonts.
+ AddType application/x-font-ttf ttc ttf
+ AddType font/opentype otf
+
+ # Make SVGZ fonts work on iPad:
+ # https://twitter.com/FontSquirrel/status/14855840545
+ AddType image/svg+xml svg svgz
+ AddEncoding gzip svgz
+
+ # Other
+ AddType application/octet-stream safariextz
+ AddType application/x-chrome-extension crx
+ AddType application/x-opera-extension oex
+ AddType application/x-shockwave-flash swf
+ AddType application/x-web-app-manifest+json webapp
+ AddType application/x-xpinstall xpi
+ AddType application/xml atom rdf rss xml
+ AddType image/webp webp
+ AddType image/x-icon ico
+ AddType text/cache-manifest appcache manifest
+ AddType text/vtt vtt
+ AddType text/x-component htc
+ AddType text/x-vcard vcf
+
+
+
+# ------------------------------------------------------------------------------
+# | UTF-8 encoding |
+# ------------------------------------------------------------------------------
+
+# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
+AddDefaultCharset utf-8
+
+# Force UTF-8 for certain file formats.
+
+ AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
+
+
+
+# ##############################################################################
+# # URL REWRITES #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Rewrite engine |
+# ------------------------------------------------------------------------------
+
+# Turning on the rewrite engine and enabling the `FollowSymLinks` option is
+# necessary for the following directives to work.
+
+# If your web host doesn't allow the `FollowSymlinks` option, you may need to
+# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
+# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
+
+# Also, some cloud hosting services require `RewriteBase` to be set:
+# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
+
+
+ Options +FollowSymlinks
+ # Options +SymLinksIfOwnerMatch
+ RewriteEngine On
+ # RewriteBase /
+
+
+# ------------------------------------------------------------------------------
+# | Suppressing / Forcing the "www." at the beginning of URLs |
+# ------------------------------------------------------------------------------
+
+# The same content should never be available under two different URLs especially
+# not with and without "www." at the beginning. This can cause SEO problems
+# (duplicate content), therefore, you should choose one of the alternatives and
+# redirect the other one.
+
+# By default option 1 (no "www.") is activated:
+# http://no-www.org/faq.php?q=class_b
+
+# If you'd prefer to use option 2, just comment out all the lines from option 1
+# and uncomment the ones from option 2.
+
+# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Option 1: rewrite www.example.com → example.com
+
+
+ RewriteCond %{HTTPS} !=on
+ RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
+ RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Option 2: rewrite example.com → www.example.com
+
+# Be aware that the following might not be a good idea if you use "real"
+# subdomains for certain parts of your website.
+
+#
+# RewriteCond %{HTTPS} !=on
+# RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
+# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
+#
+
+
+# ##############################################################################
+# # SECURITY #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Content Security Policy (CSP) |
+# ------------------------------------------------------------------------------
+
+# You can mitigate the risk of cross-site scripting and other content-injection
+# attacks by setting a Content Security Policy which whitelists trusted sources
+# of content for your site.
+
+# The example header below allows ONLY scripts that are loaded from the current
+# site's origin (no inline scripts, no CDN, etc). This almost certainly won't
+# work as-is for your site!
+
+# To get all the details you'll need to craft a reasonable policy for your site,
+# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
+# see the specification: http://w3.org/TR/CSP).
+
+#
+# Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
+#
+# Header unset Content-Security-Policy
+#
+#
+
+# ------------------------------------------------------------------------------
+# | File access |
+# ------------------------------------------------------------------------------
+
+# Block access to directories without a default document.
+# Usually you should leave this uncommented because you shouldn't allow anyone
+# to surf through every directory on your server (which may includes rather
+# private places like the CMS's directories).
+
+
+ Options -Indexes
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Block access to hidden files and directories.
+# This includes directories used by version control systems such as Git and SVN.
+
+
+ RewriteCond %{SCRIPT_FILENAME} -d [OR]
+ RewriteCond %{SCRIPT_FILENAME} -f
+ RewriteRule "(^|/)\." - [F]
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Block access to backup and source files.
+# These files may be left by some text editors and can pose a great security
+# danger when anyone has access to them.
+
+
+ Order allow,deny
+ Deny from all
+ Satisfy All
+
+
+# ------------------------------------------------------------------------------
+# | Secure Sockets Layer (SSL) |
+# ------------------------------------------------------------------------------
+
+# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
+# prevent `https://www.example.com` when your certificate only allows
+# `https://secure.example.com`.
+
+#
+# RewriteCond %{SERVER_PORT} !^443
+# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
+#
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Force client-side SSL redirection.
+
+# If a user types "example.com" in his browser, the above rule will redirect him
+# to the secure version of the site. That still leaves a window of opportunity
+# (the initial HTTP connection) for an attacker to downgrade or redirect the
+# request. The following header ensures that browser will ONLY connect to your
+# server via HTTPS, regardless of what the users type in the address bar.
+# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
+
+#
+# Header set Strict-Transport-Security max-age=16070400;
+#
+
+# ------------------------------------------------------------------------------
+# | Server software information |
+# ------------------------------------------------------------------------------
+
+# Avoid displaying the exact Apache version number, the description of the
+# generic OS-type and the information about Apache's compiled-in modules.
+
+# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
+
+# ServerTokens Prod
+
+
+# ##############################################################################
+# # WEB PERFORMANCE #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Compression |
+# ------------------------------------------------------------------------------
+
+
+
+ # Force compression for mangled headers.
+ # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
+
+
+ SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
+ RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
+
+
+
+ # Compress all output labeled with one of the following MIME-types
+ # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
+ # and can remove the `` and `` lines
+ # as `AddOutputFilterByType` is still in the core directives).
+
+ AddOutputFilterByType DEFLATE application/atom+xml \
+ application/javascript \
+ application/json \
+ application/rss+xml \
+ application/vnd.ms-fontobject \
+ application/x-font-ttf \
+ application/x-web-app-manifest+json \
+ application/xhtml+xml \
+ application/xml \
+ font/opentype \
+ image/svg+xml \
+ image/x-icon \
+ text/css \
+ text/html \
+ text/plain \
+ text/x-component \
+ text/xml
+
+
+
+
+# ------------------------------------------------------------------------------
+# | Content transformations |
+# ------------------------------------------------------------------------------
+
+# Prevent some of the mobile network providers from modifying the content of
+# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
+
+#
+# Header set Cache-Control "no-transform"
+#
+
+# ------------------------------------------------------------------------------
+# | ETag removal |
+# ------------------------------------------------------------------------------
+
+# Since we're sending far-future expires headers (see below), ETags can
+# be removed: http://developer.yahoo.com/performance/rules.html#etags.
+
+# `FileETag None` is not enough for every server.
+
+ Header unset ETag
+
+
+FileETag None
+
+# ------------------------------------------------------------------------------
+# | Expires headers (for better cache control) |
+# ------------------------------------------------------------------------------
+
+# The following expires headers are set pretty far in the future. If you don't
+# control versioning with filename-based cache busting, consider lowering the
+# cache time for resources like CSS and JS to something like 1 week.
+
+
+
+ ExpiresActive on
+ ExpiresDefault "access plus 1 month"
+
+ # CSS
+ ExpiresByType text/css "access plus 1 year"
+
+ # Data interchange
+ ExpiresByType application/json "access plus 0 seconds"
+ ExpiresByType application/xml "access plus 0 seconds"
+ ExpiresByType text/xml "access plus 0 seconds"
+
+ # Favicon (cannot be renamed!)
+ ExpiresByType image/x-icon "access plus 1 week"
+
+ # HTML components (HTCs)
+ ExpiresByType text/x-component "access plus 1 month"
+
+ # HTML
+ ExpiresByType text/html "access plus 0 seconds"
+
+ # JavaScript
+ ExpiresByType application/javascript "access plus 1 year"
+
+ # Manifest files
+ ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
+ ExpiresByType text/cache-manifest "access plus 0 seconds"
+
+ # Media
+ ExpiresByType audio/ogg "access plus 1 month"
+ ExpiresByType image/gif "access plus 1 month"
+ ExpiresByType image/jpeg "access plus 1 month"
+ ExpiresByType image/png "access plus 1 month"
+ ExpiresByType video/mp4 "access plus 1 month"
+ ExpiresByType video/ogg "access plus 1 month"
+ ExpiresByType video/webm "access plus 1 month"
+
+ # Web feeds
+ ExpiresByType application/atom+xml "access plus 1 hour"
+ ExpiresByType application/rss+xml "access plus 1 hour"
+
+ # Web fonts
+ ExpiresByType application/font-woff "access plus 1 month"
+ ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
+ ExpiresByType application/x-font-ttf "access plus 1 month"
+ ExpiresByType font/opentype "access plus 1 month"
+ ExpiresByType image/svg+xml "access plus 1 month"
+
+
+
+# ------------------------------------------------------------------------------
+# | Filename-based cache busting |
+# ------------------------------------------------------------------------------
+
+# If you're not using a build process to manage your filename version revving,
+# you might want to consider enabling the following directives to route all
+# requests such as `/css/style.12345.css` to `/css/style.css`.
+
+# To understand why this is important and a better idea than `*.css?v231`, read:
+# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
+
+#
+# RewriteCond %{REQUEST_FILENAME} !-f
+# RewriteCond %{REQUEST_FILENAME} !-d
+# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
+#
+
+# ------------------------------------------------------------------------------
+# | File concatenation |
+# ------------------------------------------------------------------------------
+
+# Allow concatenation from within specific CSS and JS files, e.g.:
+# Inside of `script.combined.js` you could have
+#
+#
+# and they would be included into this single file.
+
+#
+#
+# Options +Includes
+# AddOutputFilterByType INCLUDES application/javascript application/json
+# SetOutputFilter INCLUDES
+#
+#
+# Options +Includes
+# AddOutputFilterByType INCLUDES text/css
+# SetOutputFilter INCLUDES
+#
+#
+
+# ------------------------------------------------------------------------------
+# | Persistent connections |
+# ------------------------------------------------------------------------------
+
+# Allow multiple requests to be sent over the same TCP connection:
+# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
+
+# Enable if you serve a lot of static content but, be aware of the
+# possible disadvantages!
+
+#
+# Header set Connection Keep-Alive
+#
diff --git a/app/404.html b/app/404.html
new file mode 100644
index 0000000..f5c3819
--- /dev/null
+++ b/app/404.html
@@ -0,0 +1,157 @@
+
+
+
+
+ Page Not Found :(
+
+
+
+
+
Not found :(
+
Sorry, but the page you were trying to view does not exist.
+
It looks like this was the result of either:
+
+ - a mistyped address
+ - an out-of-date link
+
+
+
+
+
+
diff --git a/app/favicon.ico b/app/favicon.ico
new file mode 100644
index 0000000..6527905
Binary files /dev/null and b/app/favicon.ico differ
diff --git a/app/images/yeoman.png b/app/images/yeoman.png
new file mode 100644
index 0000000..92497ad
Binary files /dev/null and b/app/images/yeoman.png differ
diff --git a/app/index.html b/app/index.html
new file mode 100644
index 0000000..1cfd637
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/robots.txt b/app/robots.txt
new file mode 100644
index 0000000..9417495
--- /dev/null
+++ b/app/robots.txt
@@ -0,0 +1,3 @@
+# robotstxt.org
+
+User-agent: *
diff --git a/app/scripts/angularfire/auth.js b/app/scripts/angularfire/auth.js
new file mode 100644
index 0000000..7d322fd
--- /dev/null
+++ b/app/scripts/angularfire/auth.js
@@ -0,0 +1,8 @@
+(function() {
+ 'use strict';
+ angular.module('firebase.auth', ['firebase', 'firebase.ref'])
+
+ .factory('Auth', function($firebaseAuth, Ref) {
+ return $firebaseAuth(Ref);
+ });
+})();
diff --git a/app/scripts/angularfire/config.js b/app/scripts/angularfire/config.js
new file mode 100644
index 0000000..c92f060
--- /dev/null
+++ b/app/scripts/angularfire/config.js
@@ -0,0 +1,5 @@
+angular.module('firebase.config', [])
+ .constant('FBURL', 'https://ossu.firebaseio.com')
+ .constant('SIMPLE_LOGIN_PROVIDERS', ['github'])
+
+ .constant('loginRedirectPath', '/login');
diff --git a/app/scripts/angularfire/firebase.ref.js b/app/scripts/angularfire/firebase.ref.js
new file mode 100644
index 0000000..1470d99
--- /dev/null
+++ b/app/scripts/angularfire/firebase.ref.js
@@ -0,0 +1,5 @@
+angular.module('firebase.ref', ['firebase', 'firebase.config'])
+ .factory('Ref', ['$window', 'FBURL', function($window, FBURL) {
+ 'use strict';
+ return new $window.Firebase(FBURL);
+ }]);
diff --git a/app/scripts/app.js b/app/scripts/app.js
new file mode 100644
index 0000000..86676f6
--- /dev/null
+++ b/app/scripts/app.js
@@ -0,0 +1,22 @@
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ossuClientApp
+ * @description
+ * # ossuClientApp
+ *
+ * Main module of the application.
+ */
+angular.module('ossuClientApp', [
+ 'ngAnimate',
+ 'ngCookies',
+ 'ngMessages',
+ 'ngResource',
+ 'ngRoute',
+ 'ngSanitize',
+ 'ngTouch',
+ 'firebase',
+ 'firebase.ref',
+ 'firebase.auth'
+ ]);
diff --git a/app/scripts/controllers/account.js b/app/scripts/controllers/account.js
new file mode 100644
index 0000000..9ec330f
--- /dev/null
+++ b/app/scripts/controllers/account.js
@@ -0,0 +1,18 @@
+'use strict';
+/**
+ * @ngdoc function
+ * @name muck2App.controller:AccountCtrl
+ * @description
+ * # AccountCtrl
+ * Provides rudimentary account management functions.
+ */
+angular.module('ossuClientApp')
+ .controller('AccountCtrl', function ($scope, user, Auth, Ref, $firebaseObject, $timeout) {
+ $scope.user = user;
+ $scope.logout = function() { Auth.$unauth(); };
+ $scope.messages = [];
+ var profile = $firebaseObject(Ref.child('users/'+user.uid));
+ profile.$bindTo($scope, 'profile');
+
+
+ });
diff --git a/app/scripts/controllers/chat.js b/app/scripts/controllers/chat.js
new file mode 100644
index 0000000..c064e10
--- /dev/null
+++ b/app/scripts/controllers/chat.js
@@ -0,0 +1,33 @@
+'use strict';
+/**
+ * @ngdoc function
+ * @name ossuClientApp.controller:ChatCtrl
+ * @description
+ * # ChatCtrl
+ * A demo of using AngularFire to manage a synchronized list.
+ */
+angular.module('ossuClientApp')
+ .controller('ChatCtrl', function ($scope, Ref, $firebaseArray, $timeout) {
+ // synchronize a read-only, synchronized array of messages, limit to most recent 10
+ $scope.messages = $firebaseArray(Ref.child('messages').limitToLast(10));
+
+ // display any errors
+ $scope.messages.$loaded().catch(alert);
+
+ // provide a method for adding a message
+ $scope.addMessage = function(newMessage) {
+ if( newMessage ) {
+ // push a message to the end of the array
+ $scope.messages.$add({text: newMessage})
+ // display any errors
+ .catch(alert);
+ }
+ };
+
+ function alert(msg) {
+ $scope.err = msg;
+ $timeout(function() {
+ $scope.err = null;
+ }, 5000);
+ }
+ });
diff --git a/app/scripts/controllers/login.js b/app/scripts/controllers/login.js
new file mode 100644
index 0000000..8b20bec
--- /dev/null
+++ b/app/scripts/controllers/login.js
@@ -0,0 +1,32 @@
+'use strict';
+/**
+ * @ngdoc function
+ * @name ossuClientApp.controller:LoginCtrl
+ * @description
+ * # LoginCtrl
+ * Manages authentication to any active providers.
+ */
+angular.module('ossuClientApp')
+ .controller('LoginCtrl', function ($scope, Auth, $location) {
+ $scope.oauthLogin = function(provider) {
+ $scope.err = null;
+ Auth.$authWithOAuthPopup(provider, {rememberMe: true}).then(redirect, showError);
+ };
+
+ $scope.anonymousLogin = function() {
+ $scope.err = null;
+ Auth.$authAnonymously({rememberMe: true}).then(redirect, showError);
+ };
+
+
+
+ function redirect() {
+ $location.path('/account');
+ }
+
+ function showError(err) {
+ $scope.err = err;
+ }
+
+
+ });
diff --git a/app/scripts/controllers/main.js b/app/scripts/controllers/main.js
new file mode 100644
index 0000000..6441f4c
--- /dev/null
+++ b/app/scripts/controllers/main.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ossuClientApp.controller:MainCtrl
+ * @description
+ * # MainCtrl
+ * Controller of the ossuClientApp
+ */
+angular.module('ossuClientApp')
+ .controller('MainCtrl', function ($scope) {
+ $scope.awesomeThings = [
+ 'HTML5 Boilerplate',
+ 'AngularJS',
+ 'Karma'
+ ];
+ });
diff --git a/app/scripts/directives/ngHideAuth.js b/app/scripts/directives/ngHideAuth.js
new file mode 100644
index 0000000..4f61e97
--- /dev/null
+++ b/app/scripts/directives/ngHideAuth.js
@@ -0,0 +1,30 @@
+
+/**
+ * @ngdoc function
+ * @name ossuClientApp.directive:ngHideAuth
+ * @description
+ * # ngHideAuthDirective
+ * A directive that shows elements only when user is logged out. It also waits for Auth
+ * to be initialized so there is no initial flashing of incorrect state.
+ */
+angular.module('ossuClientApp')
+ .directive('ngHideAuth', ['Auth', '$timeout', function (Auth, $timeout) {
+ 'use strict';
+
+ return {
+ restrict: 'A',
+ link: function(scope, el) {
+ el.addClass('ng-cloak'); // hide until we process it
+ function update() {
+ // sometimes if ngCloak exists on same element, they argue, so make sure that
+ // this one always runs last for reliability
+ $timeout(function () {
+ el.toggleClass('ng-cloak', !!Auth.$getAuth());
+ }, 0);
+ }
+
+ Auth.$onAuth(update);
+ update();
+ }
+ };
+ }]);
diff --git a/app/scripts/directives/ngShowAuth.js b/app/scripts/directives/ngShowAuth.js
new file mode 100644
index 0000000..b6823ca
--- /dev/null
+++ b/app/scripts/directives/ngShowAuth.js
@@ -0,0 +1,30 @@
+/**
+ * @ngdoc function
+ * @name ossuClientApp.directive:ngShowAuth
+ * @description
+ * # ngShowAuthDirective
+ * A directive that shows elements only when user is logged in. It also waits for Auth
+ * to be initialized so there is no initial flashing of incorrect state.
+ */
+angular.module('ossuClientApp')
+ .directive('ngShowAuth', ['Auth', '$timeout', function (Auth, $timeout) {
+ 'use strict';
+
+ return {
+ restrict: 'A',
+ link: function(scope, el) {
+ el.addClass('ng-cloak'); // hide until we process it
+
+ function update() {
+ // sometimes if ngCloak exists on same element, they argue, so make sure that
+ // this one always runs last for reliability
+ $timeout(function () {
+ el.toggleClass('ng-cloak', !Auth.$getAuth());
+ }, 0);
+ }
+
+ Auth.$onAuth(update);
+ update();
+ }
+ };
+ }]);
diff --git a/app/scripts/filters/reverse.js b/app/scripts/filters/reverse.js
new file mode 100644
index 0000000..be3f31b
--- /dev/null
+++ b/app/scripts/filters/reverse.js
@@ -0,0 +1,8 @@
+'use strict';
+
+angular.module('ossuClientApp')
+ .filter('reverse', function() {
+ return function(items) {
+ return angular.isArray(items)? items.slice().reverse() : [];
+ };
+ });
diff --git a/app/scripts/routes.js b/app/scripts/routes.js
new file mode 100644
index 0000000..74416d1
--- /dev/null
+++ b/app/scripts/routes.js
@@ -0,0 +1,112 @@
+'use strict';
+/**
+ * @ngdoc overview
+ * @name ossuClientApp:routes
+ * @description
+ * # routes.js
+ *
+ * Configure routes for use with Angular, and apply authentication security
+ * Add new routes using `yo angularfire:route` with the optional --auth-required flag.
+ *
+ * Any controller can be secured so that it will only load if user is logged in by
+ * using `whenAuthenticated()` in place of `when()`. This requires the user to
+ * be logged in to view this route, and adds the current user into the dependencies
+ * which can be injected into the controller. If user is not logged in, the promise is
+ * rejected, which is handled below by $routeChangeError
+ *
+ * Any controller can be forced to wait for authentication to resolve, without necessarily
+ * requiring the user to be logged in, by adding a `resolve` block similar to the one below.
+ * It would then inject `user` as a dependency. This could also be done in the controller,
+ * but abstracting it makes things cleaner (controllers don't need to worry about auth state
+ * or timing of displaying its UI components; it can assume it is taken care of when it runs)
+ *
+ * resolve: {
+ * user: ['Auth', function(Auth) {
+ * return Auth.$getAuth();
+ * }]
+ * }
+ *
+ */
+angular.module('ossuClientApp')
+
+/**
+ * Adds a special `whenAuthenticated` method onto $routeProvider. This special method,
+ * when called, invokes Auth.$requireAuth() service (see Auth.js).
+ *
+ * The promise either resolves to the authenticated user object and makes it available to
+ * dependency injection (see AccountCtrl), or rejects the promise if user is not logged in,
+ * forcing a redirect to the /login page
+ */
+ .config(['$routeProvider', 'SECURED_ROUTES', function($routeProvider, SECURED_ROUTES) {
+ // credits for this idea: https://groups.google.com/forum/#!msg/angular/dPr9BpIZID0/MgWVluo_Tg8J
+ // unfortunately, a decorator cannot be use here because they are not applied until after
+ // the .config calls resolve, so they can't be used during route configuration, so we have
+ // to hack it directly onto the $routeProvider object
+ $routeProvider.whenAuthenticated = function(path, route) {
+ route.resolve = route.resolve || {};
+ route.resolve.user = ['Auth', function(Auth) {
+ return Auth.$requireAuth();
+ }];
+ $routeProvider.when(path, route);
+ SECURED_ROUTES[path] = true;
+ return $routeProvider;
+ };
+ }])
+
+ // configure views; whenAuthenticated adds a resolve method to ensure users authenticate
+ // before trying to access that route
+ .config(['$routeProvider', function($routeProvider) {
+ $routeProvider
+ .when('/', {
+ templateUrl: 'views/main.html',
+ controller: 'MainCtrl'
+ })
+
+ .when('/chat', {
+ templateUrl: 'views/chat.html',
+ controller: 'ChatCtrl'
+ })
+ .when('/login', {
+ templateUrl: 'views/login.html',
+ controller: 'LoginCtrl'
+ })
+ .whenAuthenticated('/account', {
+ templateUrl: 'views/account.html',
+ controller: 'AccountCtrl'
+ })
+ .otherwise({redirectTo: '/'});
+ }])
+
+ /**
+ * Apply some route security. Any route's resolve method can reject the promise with
+ * "AUTH_REQUIRED" to force a redirect. This method enforces that and also watches
+ * for changes in auth status which might require us to navigate away from a path
+ * that we can no longer view.
+ */
+ .run(['$rootScope', '$location', 'Auth', 'SECURED_ROUTES', 'loginRedirectPath',
+ function($rootScope, $location, Auth, SECURED_ROUTES, loginRedirectPath) {
+ // watch for login status changes and redirect if appropriate
+ Auth.$onAuth(check);
+
+ // some of our routes may reject resolve promises with the special {authRequired: true} error
+ // this redirects to the login page whenever that is encountered
+ $rootScope.$on('$routeChangeError', function(e, next, prev, err) {
+ if( err === 'AUTH_REQUIRED' ) {
+ $location.path(loginRedirectPath);
+ }
+ });
+
+ function check(user) {
+ if( !user && authRequired($location.path()) ) {
+ $location.path(loginRedirectPath);
+ }
+ }
+
+ function authRequired(path) {
+ return SECURED_ROUTES.hasOwnProperty(path);
+ }
+ }
+ ])
+
+ // used by route security
+ .constant('SECURED_ROUTES', {});
diff --git a/app/styles/main.scss b/app/styles/main.scss
new file mode 100644
index 0000000..f3f5429
--- /dev/null
+++ b/app/styles/main.scss
@@ -0,0 +1,91 @@
+$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/";
+// bower:scss
+@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss";
+// endbower
+
+.browsehappy {
+ margin: 0.2em 0;
+ background: #ccc;
+ color: #000;
+ padding: 0.2em 0;
+}
+
+body {
+ padding: 0;
+}
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+.header,
+.marketing,
+.footer {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+/* Custom page header */
+.header {
+ border-bottom: 1px solid #e5e5e5;
+ margin-bottom: 10px;
+
+ /* Make the masthead heading the same height as the navigation */
+ h3 {
+ margin-top: 0;
+ margin-bottom: 0;
+ line-height: 40px;
+ padding-bottom: 19px;
+ }
+}
+
+/* Custom page footer */
+.footer {
+ padding-top: 19px;
+ color: #777;
+ border-top: 1px solid #e5e5e5;
+}
+
+.container-narrow > hr {
+ margin: 30px 0;
+}
+
+/* Main marketing message and sign up button */
+.jumbotron {
+ text-align: center;
+ border-bottom: 1px solid #e5e5e5;
+
+ .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+ }
+}
+
+/* Supporting marketing content */
+.marketing {
+ margin: 40px 0;
+
+ p + h4 {
+ margin-top: 28px;
+ }
+}
+
+/* Responsive: Portrait tablets and up */
+@media screen and (min-width: 768px) {
+ .container {
+ max-width: 730px;
+ }
+
+ /* Remove the padding we set earlier */
+ .header,
+ .marketing,
+ .footer {
+ padding-left: 0;
+ padding-right: 0;
+ }
+ /* Space out the masthead */
+ .header {
+ margin-bottom: 30px;
+ }
+ /* Remove the bottom border on the jumbotron for visual effect */
+ .jumbotron {
+ border-bottom: 0;
+ }
+}
diff --git a/app/views/account.html b/app/views/account.html
new file mode 100644
index 0000000..37b7884
--- /dev/null
+++ b/app/views/account.html
@@ -0,0 +1,30 @@
+
+
+
+
Profile
+
+
+
+
+
+
+
+
+
+
+{{message.text}}
diff --git a/app/views/chat.html b/app/views/chat.html
new file mode 100644
index 0000000..67fd4ff
--- /dev/null
+++ b/app/views/chat.html
@@ -0,0 +1,13 @@
+
+Chat
+
+
+
+
+
+{{err}}
diff --git a/app/views/login.html b/app/views/login.html
new file mode 100644
index 0000000..0776bc9
--- /dev/null
+++ b/app/views/login.html
@@ -0,0 +1,10 @@
+
+Login Page
+
+
+
diff --git a/app/views/main.html b/app/views/main.html
new file mode 100644
index 0000000..42f4a03
--- /dev/null
+++ b/app/views/main.html
@@ -0,0 +1,28 @@
+
+
'Allo, 'Allo!
+
+ ![I'm Yeoman](images/yeoman.png)
+ Always a pleasure scaffolding your apps.
+
+
Splendid!
+
+
+
+
Firebase
+
+ Firebase is a powerful API to store and sync data in realtime.
+
+
+
HTML5 Boilerplate
+
+ HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.
+
+
+
Angular
+
+ AngularJS is a toolset for building the framework most suited to your application development.
+
+
+
Karma
+
Spectacular Test Runner for JavaScript.
+
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..0659463
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,26 @@
+{
+ "name": "ossu-client",
+ "version": "0.0.0",
+ "dependencies": {
+ "angular": "^1.3.0",
+ "firebase": "2.2.2",
+ "angularfire": "1.0.0",
+ "bootstrap-sass-official": "^3.2.0",
+ "angular-animate": "^1.3.0",
+ "angular-cookies": "^1.3.0",
+ "angular-messages": "^1.3.0",
+ "angular-resource": "^1.3.0",
+ "angular-route": "^1.3.0",
+ "angular-sanitize": "^1.3.0",
+ "angular-touch": "^1.3.0"
+ },
+ "devDependencies": {
+ "mockfirebase": "0.11.0",
+ "angular-mocks": "^1.3.0"
+ },
+ "appPath": "app",
+ "moduleName": "ossuClientApp",
+ "resolutions": {
+ "angular": "1.5.2"
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..96a88c6
--- /dev/null
+++ b/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "ossuclient",
+ "version": "0.0.0",
+ "dependencies": {},
+ "repository": {},
+ "devDependencies": {
+ "grunt": "^0.4.5",
+ "grunt-autoprefixer": "^2.0.0",
+ "grunt-concurrent": "^1.0.0",
+ "grunt-contrib-clean": "^0.6.0",
+ "grunt-contrib-compass": "^1.0.0",
+ "grunt-contrib-concat": "^0.5.0",
+ "grunt-contrib-connect": "^0.9.0",
+ "grunt-contrib-copy": "^0.7.0",
+ "grunt-contrib-cssmin": "^0.12.0",
+ "grunt-contrib-htmlmin": "^0.4.0",
+ "grunt-contrib-imagemin": "^0.9.2",
+ "grunt-contrib-jshint": "^0.11.0",
+ "grunt-contrib-uglify": "^0.7.0",
+ "grunt-contrib-watch": "^0.6.1",
+ "grunt-filerev": "^2.1.2",
+ "grunt-google-cdn": "^0.4.3",
+ "grunt-newer": "^1.1.0",
+ "grunt-ng-annotate": "^0.9.2",
+ "grunt-svgmin": "^2.0.0",
+ "grunt-usemin": "^3.0.0",
+ "grunt-wiredep": "^2.0.0",
+ "jshint-stylish": "^1.0.0",
+ "load-grunt-tasks": "^3.1.0",
+ "time-grunt": "^1.0.0",
+ "chalk": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+}
diff --git a/test/.jshintrc b/test/.jshintrc
new file mode 100644
index 0000000..e8b8f2b
--- /dev/null
+++ b/test/.jshintrc
@@ -0,0 +1,22 @@
+{
+ "bitwise": true,
+ "browser": true,
+ "camelcase": true,
+ "curly": true,
+ "eqeqeq": true,
+ "esnext": true,
+ "immed": true,
+ "jasmine": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "node": true,
+ "quotmark": "single",
+ "strict": true,
+ "undef": true,
+ "unused": true,
+ "globals": {
+ "angular": false,
+ "inject": false
+ }
+}
diff --git a/test/karma.conf.js b/test/karma.conf.js
new file mode 100644
index 0000000..2dd0a0b
--- /dev/null
+++ b/test/karma.conf.js
@@ -0,0 +1,85 @@
+// Karma configuration
+// Generated on 2016-03-22
+
+module.exports = function(config) {
+ 'use strict';
+
+ config.set({
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+ // base path, that will be used to resolve files and exclude
+ basePath: '../',
+
+ // testing framework to use (jasmine/mocha/qunit/...)
+ // as well as any additional frameworks (requirejs/chai/sinon/...)
+ frameworks: [
+ 'jasmine'
+ ],
+
+ // list of files / patterns to load in the browser
+ files: [
+ // bower:js
+ 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/angular/angular.js',
+ 'bower_components/firebase/firebase.js',
+ 'bower_components/angularfire/dist/angularfire.js',
+ 'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js',
+ 'bower_components/angular-animate/angular-animate.js',
+ 'bower_components/angular-cookies/angular-cookies.js',
+ 'bower_components/angular-messages/angular-messages.js',
+ 'bower_components/angular-resource/angular-resource.js',
+ 'bower_components/angular-route/angular-route.js',
+ 'bower_components/angular-sanitize/angular-sanitize.js',
+ 'bower_components/angular-touch/angular-touch.js',
+ 'bower_components/mockfirebase/browser/mockfirebase.js',
+ 'bower_components/angular-mocks/angular-mocks.js',
+ // endbower
+ 'app/scripts/**/*.js',
+ 'test/mock/**/*.js',
+ 'test/spec/**/*.js'
+ ],
+
+ // list of files / patterns to exclude
+ exclude: [
+ ],
+
+ // web server port
+ port: 8080,
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: [
+ 'PhantomJS'
+ ],
+
+ // Which plugins to enable
+ plugins: [
+ 'karma-phantomjs-launcher',
+ 'karma-jasmine'
+ ],
+
+ // Continuous Integration mode
+ // if true, it capture browsers, run tests and exit
+ singleRun: false,
+
+ colors: true,
+
+ // level of logging
+ // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+ // Uncomment the following lines if you are using grunt's server to run the tests
+ // proxies: {
+ // '/': 'http://localhost:9000/'
+ // },
+ // URL root prevent conflicts with the site root
+ // urlRoot: '_karma_'
+ });
+};
diff --git a/test/spec/controllers/main.js b/test/spec/controllers/main.js
new file mode 100644
index 0000000..0eaa7ec
--- /dev/null
+++ b/test/spec/controllers/main.js
@@ -0,0 +1,22 @@
+'use strict';
+
+describe('Controller: MainCtrl', function () {
+
+ // load the controller's module
+ beforeEach(module('ossuClientApp'));
+
+ var MainCtrl,
+ scope;
+
+ // Initialize the controller and a mock scope
+ beforeEach(inject(function ($controller, $rootScope) {
+ scope = $rootScope.$new();
+ MainCtrl = $controller('MainCtrl', {
+ $scope: scope
+ });
+ }));
+
+ it('should attach a list of awesomeThings to the scope', function () {
+ expect(scope.awesomeThings.length).toBe(3);
+ });
+});