diff --git a/.gitignore b/.gitignore
index 86fceae..b876c89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@
/libpeerconnection.log
npm-debug.log
testem.log
+
+.DS_Store
diff --git a/app/adapters/application.js b/app/adapters/application.js
new file mode 100644
index 0000000..615bbc0
--- /dev/null
+++ b/app/adapters/application.js
@@ -0,0 +1,8 @@
+import JSONAPIAdapter from 'ember-data/adapters/json-api';
+import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin';
+
+export default JSONAPIAdapter.extend(DataAdapterMixin, {
+ host: 'http://192.168.99.100:3000',
+ namespace: 'api/v1',
+ authorizer: 'authorizer:custom'
+});
diff --git a/app/authenticators/custom.js b/app/authenticators/custom.js
new file mode 100644
index 0000000..5a05fe9
--- /dev/null
+++ b/app/authenticators/custom.js
@@ -0,0 +1,47 @@
+import Ember from 'ember';
+import Base from 'ember-simple-auth/authenticators/base';
+
+export default Base.extend({
+ tokenEndpoint: 'http://192.168.99.100:3000/api/v1/authenticate',
+
+ restore(data) {
+ return new Ember.RSVP.Promise(function(resolve, reject) {
+ if (!Ember.isEmpty(data.token)) {
+ resolve(data);
+ } else {
+ reject();
+ }
+ });
+ },
+
+ authenticate(username, password) {
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ Ember.$.ajax({
+ url: this.tokenEndpoint,
+ type: 'POST',
+ data: JSON.stringify({
+ username: username,
+ password: password
+ }),
+ contentType: 'application/json',
+ dataType: 'json'
+ }).then(function(response) {
+ Ember.run(function() {
+ resolve({
+ token: response.token
+ });
+ });
+ }, function(xhr) {
+ var response = xhr.responseText;
+ Ember.run(function() {
+ reject(response);
+ });
+ });
+ });
+ },
+
+ invalidate() {
+ console.log('invalidate...');
+ return Ember.RSVP.resolve();
+ }
+});
diff --git a/app/authorizers/custom.js b/app/authorizers/custom.js
new file mode 100644
index 0000000..e443104
--- /dev/null
+++ b/app/authorizers/custom.js
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import Base from 'ember-simple-auth/authorizers/base';
+
+export default Base.extend({
+ session: Ember.inject.service('session'),
+
+ authorize(data, block) {
+ if (this.get('session.isAuthenticated') && !Ember.isEmpty(data.token)) {
+ block('x-access-token', data.token);
+ }
+ }
+});
diff --git a/app/controllers/application.js b/app/controllers/application.js
new file mode 100644
index 0000000..932ac68
--- /dev/null
+++ b/app/controllers/application.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+ session: Ember.inject.service('session')
+});
diff --git a/app/controllers/login.js b/app/controllers/login.js
new file mode 100644
index 0000000..c7758d6
--- /dev/null
+++ b/app/controllers/login.js
@@ -0,0 +1,14 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+ session: Ember.inject.service('session'),
+
+ actions: {
+ authenticate() {
+ let { username, password } = this.getProperties('username', 'password');
+ this.get('session').authenticate('authenticator:custom', username, password).catch((reason) => {
+ this.set('errorMessage', reason);
+ });
+ }
+ }
+});
diff --git a/app/controllers/project/new.js b/app/controllers/project/new.js
new file mode 100644
index 0000000..20ff394
--- /dev/null
+++ b/app/controllers/project/new.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+ actions: {
+ newProject() {
+ // create project from form values
+ let properties = this.getProperties('name');
+ var project = this.store.createRecord('project', properties);
+ }
+ }
+});
diff --git a/app/models/project.js b/app/models/project.js
new file mode 100644
index 0000000..986980a
--- /dev/null
+++ b/app/models/project.js
@@ -0,0 +1,8 @@
+import Model from 'ember-data/model';
+import attr from 'ember-data/attr';
+import belongsTo from 'ember-data/relationships';
+
+export default Model.extend({
+ name: attr('string')/*,
+ owner: belongsTo('user')*/
+});
diff --git a/app/models/user.js b/app/models/user.js
new file mode 100644
index 0000000..3af5105
--- /dev/null
+++ b/app/models/user.js
@@ -0,0 +1,10 @@
+import Model from 'ember-data/model';
+import attr from 'ember-data/attr';
+import hasMany from 'ember-data/relationships';
+
+export default Model.extend({
+ username: attr('string'),
+ password: attr('string'),
+ adminLevel: attr('number')/*,
+ projects: hasMany('project')*/
+});
diff --git a/app/router.js b/app/router.js
index 3bba78e..63851c6 100644
--- a/app/router.js
+++ b/app/router.js
@@ -6,6 +6,15 @@ const Router = Ember.Router.extend({
});
Router.map(function() {
+ this.route('login');
+
+ this.route('projects');
+ this.route('project', function() {
+ this.route('index', { path: '/:projectid' });
+ this.route('new');
+ this.route('edit', { path: '/edit/:projectid' });
+ this.route('delete', { path: '/delete/:projectid' });
+ });
});
export default Router;
diff --git a/app/routes/application.js b/app/routes/application.js
new file mode 100644
index 0000000..4891b23
--- /dev/null
+++ b/app/routes/application.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
+
+export default Ember.Route.extend(ApplicationRouteMixin, {
+ actions: {
+ invalidateSession() {
+ this.get('session').invalidate();
+ }
+ }
+});
diff --git a/app/routes/index.js b/app/routes/index.js
new file mode 100644
index 0000000..30e4e30
--- /dev/null
+++ b/app/routes/index.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
+
+export default Ember.Route.extend(AuthenticatedRouteMixin, {
+});
diff --git a/app/routes/login.js b/app/routes/login.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/app/routes/login.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/app/routes/project/delete.js b/app/routes/project/delete.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/app/routes/project/delete.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/app/routes/project/edit.js b/app/routes/project/edit.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/app/routes/project/edit.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/app/routes/project/index.js b/app/routes/project/index.js
new file mode 100644
index 0000000..b603665
--- /dev/null
+++ b/app/routes/project/index.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
+
+export default Ember.Route.extend(AuthenticatedRouteMixin, {
+ model(params) {
+ return this.store.findRecord('project', params.projectid);
+ }
+});
diff --git a/app/routes/project/new.js b/app/routes/project/new.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/app/routes/project/new.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/app/routes/projects.js b/app/routes/projects.js
new file mode 100644
index 0000000..ce96e88
--- /dev/null
+++ b/app/routes/projects.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
+
+export default Ember.Route.extend(AuthenticatedRouteMixin, {
+ model() {
+ return this.store.findAll('project');
+ }
+});
diff --git a/app/serializers/application.js b/app/serializers/application.js
new file mode 100644
index 0000000..8c80d9f
--- /dev/null
+++ b/app/serializers/application.js
@@ -0,0 +1,5 @@
+import JSONSerializer from 'ember-data/serializers/json';
+
+export default JSONSerializer.extend({
+ primaryKey: '_id'
+});
diff --git a/app/styles/app.css b/app/styles/app.css
index e69de29..c3f270c 100644
--- a/app/styles/app.css
+++ b/app/styles/app.css
@@ -0,0 +1,106 @@
+* {
+ margin: 0;
+ padding: 0;
+}
+
+/**
+ * Application skeleton
+ */
+.ember-application {
+ min-width: 800px;
+
+ background: #ddd;
+ color: #4d4d4d;
+
+ font: 16px 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ font-smoothing: antialiased;
+ -webkit-font-smoothing: antialiased;
+ -moz-font-smoothing: antialiased;
+}
+
+header {
+ width: 100%;
+ height: 50px;
+
+ padding: 10px 0 0 0;
+
+ color: #fff;
+ background-color: #151;
+}
+
+header h1 {
+ width: 100%;
+
+ text-align: center
+}
+
+footer {
+ width: 100%;
+
+ color: #666;
+
+ margin-top: 20px;
+
+ text-align: center;
+}
+
+/**
+ * Main layout
+ */
+#main-menu {
+ float: left;
+
+ width: 125px;
+
+ background-color: #fff;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
+ 0 9px 18px 0 rgba(0, 0, 0, 0.1);
+
+ margin: 20px 0 0 20px;
+ padding: 20px 20px 20px 30px;
+}
+
+#wrapper {
+ min-height: 100px;
+
+ background-color: #fff;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
+ 0 9px 18px 0 rgba(0, 0, 0, 0.1);
+
+ margin: 20px 20px 20px 220px;
+ padding: 20px;
+}
+
+/**
+ * Login layout
+ */
+#login-container {
+ width: 320px;
+ height: 180px;
+
+ background-color: #fff;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
+ 0 9px 18px 0 rgba(0, 0, 0, 0.1);
+
+ margin: 80px auto;
+ padding: 0px;
+}
+
+#login-container h1 {
+ background-color: #cdcdcd;
+
+ text-align: center;
+
+ font-size: 24;
+
+ padding: 10px 0;
+}
+
+#login {
+
+}
+
+#login-form {
+ padding: 20px 20px;
+}
diff --git a/app/templates/application.hbs b/app/templates/application.hbs
index f8bc38e..4767d55 100644
--- a/app/templates/application.hbs
+++ b/app/templates/application.hbs
@@ -1,3 +1,26 @@
-
Welcome to Ember
+
-{{outlet}}
+{{#if session.isAuthenticated}}
+
+
Menu
+
+
+ - {{#link-to 'index'}}Home{{/link-to}}
+ - {{#link-to 'projects'}}Projects{{/link-to}}
+ - Preferences
+ - Logout
+
+
+
+
+{{else}}
+ {{outlet}}
+{{/if}}
+
+
diff --git a/app/templates/index.hbs b/app/templates/index.hbs
new file mode 100644
index 0000000..700204b
--- /dev/null
+++ b/app/templates/index.hbs
@@ -0,0 +1 @@
+Main Content
diff --git a/app/templates/login.hbs b/app/templates/login.hbs
new file mode 100644
index 0000000..498b585
--- /dev/null
+++ b/app/templates/login.hbs
@@ -0,0 +1,19 @@
+
diff --git a/app/templates/project/delete.hbs b/app/templates/project/delete.hbs
new file mode 100644
index 0000000..b797135
--- /dev/null
+++ b/app/templates/project/delete.hbs
@@ -0,0 +1 @@
+Delete Project
diff --git a/app/templates/project/edit.hbs b/app/templates/project/edit.hbs
new file mode 100644
index 0000000..5f7d84b
--- /dev/null
+++ b/app/templates/project/edit.hbs
@@ -0,0 +1 @@
+Edit {{model.name}}
diff --git a/app/templates/project/index.hbs b/app/templates/project/index.hbs
new file mode 100644
index 0000000..aa24e7a
--- /dev/null
+++ b/app/templates/project/index.hbs
@@ -0,0 +1,4 @@
+{{model.name}}
+
+{{#link-to "project.edit" model}}Edit project{{/link-to}}
+{{#link-to "project.delete" model}}Delete project{{/link-to}}
diff --git a/app/templates/project/new.hbs b/app/templates/project/new.hbs
new file mode 100644
index 0000000..ac591bb
--- /dev/null
+++ b/app/templates/project/new.hbs
@@ -0,0 +1,16 @@
+New project
+
+
diff --git a/app/templates/projects.hbs b/app/templates/projects.hbs
new file mode 100644
index 0000000..70aae57
--- /dev/null
+++ b/app/templates/projects.hbs
@@ -0,0 +1,9 @@
+Projects
+
+
+ {{#each model as |project|}}
+ - {{#link-to "project.index" project.id}}{{project.name}}{{/link-to}}
+ {{/each}}
+
+
+{{#link-to "project.new"}}New project{{/link-to}}
diff --git a/package.json b/package.json
index fc3c8dd..7c3e27c 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"ember-export-application-global": "^1.0.5",
"ember-load-initializers": "^0.5.1",
"ember-resolver": "^2.0.3",
- "loader.js": "^4.0.1"
+ "loader.js": "^4.0.1",
+ "ember-simple-auth": "^1.1.0"
}
}
diff --git a/tests/unit/adapters/application-test.js b/tests/unit/adapters/application-test.js
new file mode 100644
index 0000000..f0a2101
--- /dev/null
+++ b/tests/unit/adapters/application-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('adapter:application', 'Unit | Adapter | application', {
+ // Specify the other units that are required for this test.
+ // needs: ['serializer:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let adapter = this.subject();
+ assert.ok(adapter);
+});
diff --git a/tests/unit/controllers/application-test.js b/tests/unit/controllers/application-test.js
new file mode 100644
index 0000000..b71b4a5
--- /dev/null
+++ b/tests/unit/controllers/application-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:application', 'Unit | Controller | application', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let controller = this.subject();
+ assert.ok(controller);
+});
diff --git a/tests/unit/controllers/login-test.js b/tests/unit/controllers/login-test.js
new file mode 100644
index 0000000..b68f797
--- /dev/null
+++ b/tests/unit/controllers/login-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:login', 'Unit | Controller | login', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let controller = this.subject();
+ assert.ok(controller);
+});
diff --git a/tests/unit/controllers/projects/new-test.js b/tests/unit/controllers/projects/new-test.js
new file mode 100644
index 0000000..1a5e3ea
--- /dev/null
+++ b/tests/unit/controllers/projects/new-test.js
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:projects/new', 'Unit | Controller | projects/new', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let controller = this.subject();
+ assert.ok(controller);
+});
diff --git a/tests/unit/models/project-test.js b/tests/unit/models/project-test.js
new file mode 100644
index 0000000..2dddcd6
--- /dev/null
+++ b/tests/unit/models/project-test.js
@@ -0,0 +1,12 @@
+import { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('project', 'Unit | Model | project', {
+ // Specify the other units that are required for this test.
+ needs: []
+});
+
+test('it exists', function(assert) {
+ let model = this.subject();
+ // let store = this.store();
+ assert.ok(!!model);
+});
diff --git a/tests/unit/models/user-test.js b/tests/unit/models/user-test.js
new file mode 100644
index 0000000..ba21110
--- /dev/null
+++ b/tests/unit/models/user-test.js
@@ -0,0 +1,12 @@
+import { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('user', 'Unit | Model | user', {
+ // Specify the other units that are required for this test.
+ needs: []
+});
+
+test('it exists', function(assert) {
+ let model = this.subject();
+ // let store = this.store();
+ assert.ok(!!model);
+});
diff --git a/tests/unit/routes/application-test.js b/tests/unit/routes/application-test.js
new file mode 100644
index 0000000..9808c43
--- /dev/null
+++ b/tests/unit/routes/application-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:application', 'Unit | Route | application', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/index-test.js b/tests/unit/routes/index-test.js
new file mode 100644
index 0000000..5d0f50d
--- /dev/null
+++ b/tests/unit/routes/index-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:index', 'Unit | Route | index', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/login-test.js b/tests/unit/routes/login-test.js
new file mode 100644
index 0000000..e78ebad
--- /dev/null
+++ b/tests/unit/routes/login-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:login', 'Unit | Route | login', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects-test.js b/tests/unit/routes/projects-test.js
new file mode 100644
index 0000000..e5dfb65
--- /dev/null
+++ b/tests/unit/routes/projects-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects', 'Unit | Route | projects', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects/delete-test.js b/tests/unit/routes/projects/delete-test.js
new file mode 100644
index 0000000..7ce43e6
--- /dev/null
+++ b/tests/unit/routes/projects/delete-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects/delete', 'Unit | Route | projects/delete', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects/edit-test.js b/tests/unit/routes/projects/edit-test.js
new file mode 100644
index 0000000..545616f
--- /dev/null
+++ b/tests/unit/routes/projects/edit-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects/edit', 'Unit | Route | projects/edit', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects/index-test.js b/tests/unit/routes/projects/index-test.js
new file mode 100644
index 0000000..c232f73
--- /dev/null
+++ b/tests/unit/routes/projects/index-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects/index', 'Unit | Route | projects/index', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects/new-test.js b/tests/unit/routes/projects/new-test.js
new file mode 100644
index 0000000..0bb6b03
--- /dev/null
+++ b/tests/unit/routes/projects/new-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects/new', 'Unit | Route | projects/new', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/routes/projects/project-test.js b/tests/unit/routes/projects/project-test.js
new file mode 100644
index 0000000..fa2d3fe
--- /dev/null
+++ b/tests/unit/routes/projects/project-test.js
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:projects/project', 'Unit | Route | projects/project', {
+ // Specify the other units that are required for this test.
+ // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+ let route = this.subject();
+ assert.ok(route);
+});
diff --git a/tests/unit/serializers/application-test.js b/tests/unit/serializers/application-test.js
new file mode 100644
index 0000000..705e9ec
--- /dev/null
+++ b/tests/unit/serializers/application-test.js
@@ -0,0 +1,15 @@
+import { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('application', 'Unit | Serializer | application', {
+ // Specify the other units that are required for this test.
+ needs: ['serializer:application']
+});
+
+// Replace this with your real tests.
+test('it serializes records', function(assert) {
+ let record = this.subject();
+
+ let serializedRecord = record.serialize();
+
+ assert.ok(serializedRecord);
+});