From b1e219f662064db886f1c65de139ddae21ec4459 Mon Sep 17 00:00:00 2001
From: mohiit1502
Date: Sat, 12 May 2018 04:47:41 +0530
Subject: [PATCH] Alpha
---
._.bowerrc | Bin 4096 -> 0 bytes
._.gitignore | Bin 4096 -> 0 bytes
._.jshintrc | Bin 4096 -> 0 bytes
._.travis.yml | Bin 4096 -> 0 bytes
._LICENSE | Bin 4096 -> 0 bytes
._README.md | Bin 4096 -> 0 bytes
._bower.json | Bin 4096 -> 0 bytes
._karma.conf.js | Bin 4096 -> 0 bytes
._package.json | Bin 4096 -> 0 bytes
.bowerrc | 3 -
.jshintrc | 13 --
.travis.yml | 14 --
app/api.py | 131 ---------------
app/index.html | 49 ------
app/view1/._view1.html | Bin 4096 -> 0 bytes
app/view1/._view1.js | Bin 4096 -> 0 bytes
app/view1/._view1_test.js | Bin 4096 -> 0 bytes
app/view1/view1.html | 1 -
app/view1/view1.js | 14 --
app/view1/view1_test.js | 16 --
app/view2/._view2.html | Bin 4096 -> 0 bytes
app/view2/._view2.js | Bin 4096 -> 0 bytes
app/view2/._view2_test.js | Bin 4096 -> 0 bytes
app/view2/view2.html | 5 -
app/view2/view2.js | 14 --
app/view2/view2_test.js | 16 --
{app => app_fb}/__init__.py | 6 +-
app_fb/api.py | 218 +++++++++++++++++++++++++
{app => app_fb}/models/__init__.py | 0
app_fb/models/post.py | 79 +++++++++
{app => app_fb}/models/product.py | 2 +-
{app => app_fb}/models/user.py | 53 +++++-
{app => app_fb}/static/admin.html | 0
{app => app_fb}/static/blocks.css | 0
app_fb/static/images/image.png | Bin 0 -> 104327 bytes
{app => app_fb}/templates/cart.html | 0
app_fb/templates/index.html | 64 ++++++++
{app => app_fb}/templates/profile.html | 0
{app => app_fb}/templates/results.html | 0
{app => app_fb}/templates/users.html | 10 +-
{app => app_fb}/views.py | 3 +-
bower.json | 15 --
config.json | 2 +-
karma.conf.js | 33 ----
package.json | 34 ----
run.py | 2 +-
46 files changed, 423 insertions(+), 374 deletions(-)
delete mode 100644 ._.bowerrc
delete mode 100644 ._.gitignore
delete mode 100644 ._.jshintrc
delete mode 100644 ._.travis.yml
delete mode 100644 ._LICENSE
delete mode 100644 ._README.md
delete mode 100644 ._bower.json
delete mode 100644 ._karma.conf.js
delete mode 100644 ._package.json
delete mode 100644 .bowerrc
delete mode 100644 .jshintrc
delete mode 100644 .travis.yml
delete mode 100644 app/api.py
delete mode 100644 app/index.html
delete mode 100644 app/view1/._view1.html
delete mode 100644 app/view1/._view1.js
delete mode 100644 app/view1/._view1_test.js
delete mode 100644 app/view1/view1.html
delete mode 100644 app/view1/view1.js
delete mode 100644 app/view1/view1_test.js
delete mode 100644 app/view2/._view2.html
delete mode 100644 app/view2/._view2.js
delete mode 100644 app/view2/._view2_test.js
delete mode 100644 app/view2/view2.html
delete mode 100644 app/view2/view2.js
delete mode 100644 app/view2/view2_test.js
rename {app => app_fb}/__init__.py (60%)
create mode 100644 app_fb/api.py
rename {app => app_fb}/models/__init__.py (100%)
create mode 100644 app_fb/models/post.py
rename {app => app_fb}/models/product.py (98%)
rename {app => app_fb}/models/user.py (64%)
rename {app => app_fb}/static/admin.html (100%)
rename {app => app_fb}/static/blocks.css (100%)
create mode 100644 app_fb/static/images/image.png
rename {app => app_fb}/templates/cart.html (100%)
create mode 100644 app_fb/templates/index.html
rename {app => app_fb}/templates/profile.html (100%)
rename {app => app_fb}/templates/results.html (100%)
rename {app => app_fb}/templates/users.html (82%)
rename {app => app_fb}/views.py (80%)
delete mode 100644 bower.json
delete mode 100644 karma.conf.js
delete mode 100644 package.json
diff --git a/._.bowerrc b/._.bowerrc
deleted file mode 100644
index fafd92fe096b2da23f24ab391a9197a02fe26763..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4096
zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;FvU8^
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;FvU8^
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;FvU8^
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;FvU8^
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB) /dev/null &
- - npm run update-webdriver
- - sleep 1 # give server time to start
-
-script:
- - node_modules/.bin/karma start karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox
- - node_modules/.bin/protractor e2e-tests/protractor.conf.js --browser=firefox
diff --git a/app/api.py b/app/api.py
deleted file mode 100644
index 8152f04..0000000
--- a/app/api.py
+++ /dev/null
@@ -1,131 +0,0 @@
-from flask import request, Response, render_template, send_from_directory
-from mini_amazon import app
-from mini_amazon.models.product import Product, MongoProduct
-from mini_amazon.models.user import User, MongoUser
-
-mongo_product = MongoProduct()
-mongo_user = MongoUser()
-product_list = []
-
-
-@app.route('/health', methods=['GET'])
-def health():
- return 'healthy'
-
-
-@app.route('/api/product', methods=['POST', 'GET'])
-def products():
- if request.method == 'GET':
- matches = mongo_product.search_by_name(request.args['name'])
- output_type = request.args.get('output_type', None)
- if output_type == 'html':
- return render_template('results.html', results=matches, query=request.args['name'], user_id=request.args.get('user_id'))
- else:
- return Response(str(matches), mimetype='application/json', status=200)
- elif request.method == 'POST':
- product = dict()
- operation_type = request.form.get('operation_type', None)
- if operation_type is not None:
- if operation_type == 'add':
- product['_id'] = request.form['_id']
- product['name'] = request.form['name']
- product['description'] = request.form['description']
- product['price'] = request.form['price']
- # p = Product(12, request.form['name'], request.form['description'], request.form['price'])
- mongo_product.save(product)
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
- elif operation_type == 'delete':
- _id = request.form.get('_id')
- mongo_product.delete_by_id(_id)
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
- elif operation_type == 'update':
- p = Product(request.form['name'], request.form['description'], request.form['price'])
- mongo_product.update_by_id(request.form['_id'], p)
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
- db.products.update_one(update={'$set': product}, filter={'name': currentname})
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
-
-
-@app.route('/listProducts', methods=['GET'])
-def list_all():
- matching_prods = mongo_product.list_all_products()
- matches = []
- for prod in matching_prods:
- matches.append(prod)
- return Response(str(matches), mimetype='application/json', status=200)
-
-
-@app.route('/addStuff', methods=['GET'])
-def add_stuff():
- mongo_product.add_stuff()
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
-
-
-@app.route('/api/user/', methods=['GET', 'POST'])
-def user_actions(action):
- if action == 'login':
- user = User(None, None, request.form.get('username'), request.form.get('password'))
- is_valid = mongo_user.authenticate(user)
- name = mongo_user.find_user_name_by_credentials(user)
- if is_valid is not None and is_valid:
- return render_template('profile.html', sign_up_msg="Welcome to Mini-Amazon", name = name if name is not None else "Anonymous", user_id=mongo_user.get_id_by_username(request.form.get('username')))
- else:
- return render_template("index.html", message="Invalid Username/Password")
- elif action == 'signup':
- user = dict()
- user['name'] = request.form.get('name')
- user['email'] = request.form.get('email')
- user['username'] = request.form.get('username')
- user['password'] = request.form.get('password')
- does_user_exist = mongo_user.check_if_user_exists(request.form.get('username'))
- if does_user_exist:
- return render_template("index.html", user_exists_msg="Username exists, please enter a different user name!")
- else:
- mongo_user.save(user)
- return Response(str({'status' : 'User Added!'}), mimetype='application/json', status=200)
-
- else:
- status = {
- 'status' : 'Invalid Action'
- }
- return Response(str(status), mimetype='application/json', status=400)
-
-
-@app.route('/listUsers', methods=['GET'])
-def list_all_users():
- matching_users = mongo_user.list_all_users()
- matches = []
- if matching_users is not None:
- for user in matching_users:
- matches.append(user)
- return render_template('users.html', results=matches)
-
-
-@app.route('/addUsers', methods=['GET'])
-def add_users():
- mongo_user.add_stuff()
- return Response(str({'status': 'success'}), mimetype='application/json', status=200)
-
-@app.route('/api/cart', methods=['GET','POST'])
-def cart():
- if request.args.get('op_type') == 'getcart':
- userId = request.args.get('user_id')
- matched_ids = mongo_user.get_usercart_by_userid(userId)
- matches = mongo_product.get_product_list_from_product_ids(matched_ids)
- return render_template('cart.html', user_id=userId, results=matches)
- elif request.args.get('op_type') == 'addToCart':
- pass
- else:
- user_id = request.args.get('user_id',None)
- product_id = request.args.get('product_id', None)
-
- user= mongo_user.get_by_id(user_id)
- success = mongo_user.add_to_cart(user_id,product_id)
- user_data = mongo_user.get_by_id(user_id)
-
- return render_template('profile.html',name=user_data['name'],user_id=user_id)
-
-
-# @app.route('/admin.html')
-# def admin_tasks():
-# return render_template('../../static/admin.html')
diff --git a/app/index.html b/app/index.html
deleted file mode 100644
index c4fd228..0000000
--- a/app/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
- ngSocial App
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/view1/._view1.html b/app/view1/._view1.html
deleted file mode 100644
index 6c8ce97dafef6bbe1c137c4d7314f130b6d1afe3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4096
zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)This is the partial for view 1.
diff --git a/app/view1/view1.js b/app/view1/view1.js
deleted file mode 100644
index dbf15ef..0000000
--- a/app/view1/view1.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use strict';
-
-angular.module('ngSocial.view1', ['ngRoute'])
-
-.config(['$routeProvider', function($routeProvider) {
- $routeProvider.when('/view1', {
- templateUrl: 'view1/view1.html',
- controller: 'View1Ctrl'
- });
-}])
-
-.controller('View1Ctrl', [function() {
-
-}]);
\ No newline at end of file
diff --git a/app/view1/view1_test.js b/app/view1/view1_test.js
deleted file mode 100644
index 14ba79b..0000000
--- a/app/view1/view1_test.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict';
-
-describe('myApp.view1 module', function() {
-
- beforeEach(module('myApp.view1'));
-
- describe('view1 controller', function(){
-
- it('should ....', inject(function($controller) {
- //spec body
- var view1Ctrl = $controller('View1Ctrl');
- expect(view1Ctrl).toBeDefined();
- }));
-
- });
-});
\ No newline at end of file
diff --git a/app/view2/._view2.html b/app/view2/._view2.html
deleted file mode 100644
index 6c8ce97dafef6bbe1c137c4d7314f130b6d1afe3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4096
zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF
zKST$^44`s#G%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4$lBD@!Z^*;Fx5K9
zF({_O$iTItq$n}DB)This is the partial for view 2.
-
- Showing of 'interpolate' filter:
- {{ 'Current version is v%VERSION%.' | interpolate }}
-
diff --git a/app/view2/view2.js b/app/view2/view2.js
deleted file mode 100644
index 5e5d25f..0000000
--- a/app/view2/view2.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use strict';
-
-angular.module('ngSocial.view2', ['ngRoute'])
-
-.config(['$routeProvider', function($routeProvider) {
- $routeProvider.when('/view2', {
- templateUrl: 'view2/view2.html',
- controller: 'View2Ctrl'
- });
-}])
-
-.controller('View2Ctrl', [function() {
-
-}]);
\ No newline at end of file
diff --git a/app/view2/view2_test.js b/app/view2/view2_test.js
deleted file mode 100644
index 07b34d6..0000000
--- a/app/view2/view2_test.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict';
-
-describe('myApp.view2 module', function() {
-
- beforeEach(module('myApp.view2'));
-
- describe('view2 controller', function(){
-
- it('should ....', inject(function($controller) {
- //spec body
- var view2Ctrl = $controller('View2Ctrl');
- expect(view2Ctrl).toBeDefined();
- }));
-
- });
-});
\ No newline at end of file
diff --git a/app/__init__.py b/app_fb/__init__.py
similarity index 60%
rename from app/__init__.py
rename to app_fb/__init__.py
index 21be0d9..8546fe8 100644
--- a/app/__init__.py
+++ b/app_fb/__init__.py
@@ -1,8 +1,10 @@
from flask import Flask
+from flask_cors import CORS
-app = Flask('mini_amazon',
+app = Flask('app_fb',
static_folder='./static',
static_url_path='',
template_folder='./templates')
+CORS(app)
-from mini_amazon import views, api
\ No newline at end of file
+from app_fb import views, api
diff --git a/app_fb/api.py b/app_fb/api.py
new file mode 100644
index 0000000..68d9d93
--- /dev/null
+++ b/app_fb/api.py
@@ -0,0 +1,218 @@
+from flask import request, Response, render_template, send_from_directory
+from app_fb import app
+from app_fb.models.product import Product, MongoProductDao
+from app_fb.models.user import User, MongoUserDao
+import json
+from bson import ObjectId
+import datetime
+
+mongo_product_dao = MongoProductDao()
+mongo_user_dao = MongoUserDao()
+product_list = []
+
+
+@app.route('/health', methods=['GET'])
+def health():
+ return 'healthy'
+
+
+@app.route('/api/product', methods=['POST', 'GET'])
+def products():
+ if request.method == 'GET':
+ matches = mongo_product_dao.search_by_name(request.args['name'])
+ output_type = request.args.get('output_type', None)
+ if output_type == 'html':
+ return render_template('results.html', results=matches, query=request.args['name'], user_id=request.args.get('user_id'))
+ else:
+ return Response(str(matches), mimetype='application/json', status=200)
+ elif request.method == 'POST':
+ product = dict()
+ operation_type = request.form.get('operation_type', None)
+ if operation_type is not None:
+ if operation_type == 'add':
+ product['_id'] = request.form['_id']
+ product['name'] = request.form['name']
+ product['description'] = request.form['description']
+ product['price'] = request.form['price']
+ # p = Product(12, request.form['name'], request.form['description'], request.form['price'])
+ mongo_product_dao.save(product)
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+ elif operation_type == 'delete':
+ _id = request.form.get('_id')
+ mongo_product_dao.delete_by_id(_id)
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+ elif operation_type == 'update':
+ p = Product(request.form['name'], request.form['description'], request.form['price'])
+ mongo_product_dao.update_by_id(request.form['_id'], p)
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+ db.products.update_one(update={'$set': product}, filter={'name': currentname})
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+
+
+@app.route('/listProducts', methods=['GET'])
+def list_all():
+ matching_prods = mongo_product_dao.list_all_products()
+ matches = []
+ for prod in matching_prods:
+ matches.append(prod)
+ return Response(str(matches), mimetype='application/json', status=200)
+
+
+@app.route('/addStuff', methods=['GET'])
+def add_stuff():
+ mongo_product_dao.add_stuff()
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+
+
+@app.route('/api/user/', methods=['GET', 'POST'])
+def user_actions(action):
+ if action == 'login':
+ username = request.form.get('username')
+ password = request.form.get('password')
+ user = User(username, password, None, None, None, None, None, None, None, None, None, 'http://127.0.0.1:5003/app/images/image.png')
+ is_valid = mongo_user_dao.authenticate(user)
+ name = mongo_user_dao.find_user_name_by_credentials(user)
+ if is_valid is not None and is_valid:
+ return render_template('profile.html', sign_up_msg="Welcome to Facebook", name = name if name is not None else "Anonymous", user_id=mongo_user_dao.get_id_by_username(username))
+ else:
+ return render_template("index.html", message="Invalid Username/Password")
+ elif action == 'signup':
+ user = dict()
+ user['name'] = request.form.get('name')
+ user['email'] = request.form.get('email')
+ user['username'] = request.form.get('username')
+ user['password'] = request.form.get('password')
+ does_user_exist = mongo_user_dao.check_if_user_exists(request.form.get('username'))
+ if does_user_exist:
+ return render_template("index1.html", user_exists_msg="Username exists, please enter a different user name!")
+ else:
+ mongo_user_dao.save(user)
+ return Response(str({'status' : 'User Added!'}), mimetype='application/json', status=200)
+
+ else:
+ status = {
+ 'status' : 'Invalid Action'
+ }
+ return Response(str(status), mimetype='application/json', status=400)
+
+
+@app.route('/listUsers', methods=['GET'])
+def list_all_users():
+ matching_users = mongo_user_dao.list_all_users()
+ matches = []
+ if matching_users is not None:
+ for user in matching_users:
+ matches.append(user)
+ return render_template('users.html', results=matches)
+
+
+@app.route('/addUsers', methods=['GET'])
+def add_users():
+ mongo_user_dao.add_stuff()
+ return Response(str({'status': 'success'}), mimetype='application/json', status=200)
+
+@app.route('/api/cart', methods=['GET','POST'])
+def cart():
+ if request.args.get('op_type') == 'getcart':
+ userId = request.args.get('user_id')
+ matched_ids = mongo_user_dao.get_usercart_by_userid(userId)
+ matches = mongo_product_dao.get_product_list_from_product_ids(matched_ids)
+ return render_template('cart.html', user_id=userId, results=matches)
+ elif request.args.get('op_type') == 'addToCart':
+ pass
+ else:
+ user_id = request.args.get('user_id',None)
+ product_id = request.args.get('product_id', None)
+
+ user= mongo_user_dao.get_by_id(user_id)
+ success = mongo_user_dao.add_to_cart(user_id,product_id)
+ user_data = mongo_user_dao.get_by_id(user_id)
+
+ return render_template('profile.html',name=user_data['name'],user_id=user_id)
+
+
+# @app.route('/admin.html')
+# def admin_tasks():
+# return render_template('../../static/admin.html')
+
+@app.route('/app/authenticate', methods=['GET'])
+def authenticate():
+ username = request.args.get('username')
+ password = request.args.get('password')
+ user = User(username, password, None, None, None, None, None, None, None, None, None, None, None, None, None)
+ is_valid = mongo_user_dao.authenticate(user)
+ name = mongo_user_dao.find_user_name_by_credentials(user)
+ if is_valid is not None and is_valid:
+ _id = mongo_user_dao.get_id_by_username(username)
+ data = {
+ 'status': True,
+ '_id':_id
+ }
+ response = app.response_class(
+ response=json.dumps(JSONEncoder().encode(data)),
+ status=200,
+ mimetype='application/json'
+ )
+ else:
+ data = {
+ 'status': False,
+ 'error': 'Invalid Username/Password'
+ }
+ response = app.response_class(
+ response=json.dumps(JSONEncoder().encode(data)),
+ status=401,
+ mimetype='application/json'
+ )
+ return response
+
+
+
+@app.route('/app/getUserInfo', methods=['GET'])
+def get_user_data():
+ _id = request.args.get('_id')
+ user = mongo_user_dao.get_by_id(_id)
+ response = app.response_class(
+ response=json.dumps(JSONEncoder().encode(user)),
+ status=200,
+ mimetype='application/json'
+ )
+ return response
+
+@app.route('/app/feed', methods=['POST', 'GET'])
+def write_post():
+ if request.method == 'POST':
+ _id = request.form.get('_id')
+ post_content = request.form.get('post')
+ post = dict()
+ post['post_content'] = post_content
+ post['post_type'] = 'text/plain'
+ post['updated_time'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
+ post['likes'] = 0
+ post['comments'] = []
+ post['user'] = _id
+ post['size'] = len(post_content)
+ mongo_user_dao.add_user_post(post, _id)
+ success_msg = {'msg' : 'Thanks for posting'}
+ response = app.response_class(
+ response=json.dumps(JSONEncoder().encode(success_msg)),
+ status=200,
+ mimetype='application/json'
+ )
+ elif request.method == 'GET':
+ _id = request.args.get('_id')
+ posts = mongo_user_dao.get_user_posts(_id)
+ if posts is None:
+ posts = []
+ response = app.response_class(
+ response=json.dumps(JSONEncoder().encode(posts)),
+ status=200,
+ mimetype='application/json'
+ )
+ return response
+
+
+class JSONEncoder(json.JSONEncoder):
+ def default(self, o):
+ if isinstance(o, ObjectId):
+ return str(o)
+ return json.JSONEncoder.default(self, o)
\ No newline at end of file
diff --git a/app/models/__init__.py b/app_fb/models/__init__.py
similarity index 100%
rename from app/models/__init__.py
rename to app_fb/models/__init__.py
diff --git a/app_fb/models/post.py b/app_fb/models/post.py
new file mode 100644
index 0000000..0a9691c
--- /dev/null
+++ b/app_fb/models/post.py
@@ -0,0 +1,79 @@
+from pymongo import MongoClient
+import re
+from bson import ObjectId
+import json
+from app_fb.models.user import MongoUserDao
+
+mongo_user_dao = MongoUserDao()
+
+class Post:
+ def __init__(self, user, post_type, post_content, updated_time, post_size, likes, comments):
+ self.user = user
+ self.post_type = post_type
+ self.post_content = post_content
+ self.updated_time = updated_time
+ self.post_size = post_size
+ self.likes = likes
+ self.comments = comments
+
+
+class MongoPostDao:
+ def __init__(self):
+ config = json.load(open('./config.json', 'r'))
+ client = MongoClient(config['mongo_host'], config['mongo_port'])
+ self.db = client[config['db_name']]
+
+ def save(self, post):
+ self.db.posts.insert_one(post)
+
+ def search_by_content(self, post_content):
+ result_cursor = self.db.posts.find({'post_content': re.compile(post_content, re.IGNORECASE)})
+ matches = []
+ for post in result_cursor:
+ matches.append(post)
+ return matches
+
+ def delete_by_id(self, _id):
+ self.db.posts.delete_one({'_id': ObjectId(_id)})
+
+ def update_by_id(self, _id, post):
+ self.db.posts.update_one({'_id': ObjectId(_id)}, {'$set': post})
+
+ def list_all_posts_for_user(self, user_id):
+ user = mongo_user_dao.get_by_id(user_id)
+ if 'posts' in user:
+ return user['posts']
+ else:
+ return []
+
+ def find_posts_by_type(self, post_type):
+ a = 3 if True else 1
+ result_cursor = self.db.posts.find({'post_type': post_type})
+ matches = []
+ for post in result_cursor:
+ matches.append(post)
+ return matches[0]['first_name'] + " " + matches[0]['last_name'] if len(matches) > 0 else None
+
+ def get_by_id(self, _id):
+ query = {
+ '_id': ObjectId(_id)
+ }
+ cursor = self.db.posts.find(query)
+ post = cursor[0] if cursor.count() > 0 else None
+ return post
+
+ def get_id_by_post_content(self, post_content):
+ cursor = self.db.posts.find({'post_content': post_content})
+ post_data = cursor[0] if cursor.count() > 0 else None
+ if post_data is None:
+ return "No posts found"
+ else:
+ matches = []
+ for post in cursor:
+ matches.append(post)
+ return matches[0]['_id']
+
+ def get_comments_by_postid(self, post_id):
+ post = self.get_by_id(post_id)
+ return post['comments']
+
diff --git a/app/models/product.py b/app_fb/models/product.py
similarity index 98%
rename from app/models/product.py
rename to app_fb/models/product.py
index 1c93f6a..16795eb 100644
--- a/app/models/product.py
+++ b/app_fb/models/product.py
@@ -11,7 +11,7 @@ class Product:
self.price = price
-class MongoProduct:
+class MongoProductDao:
def __init__(self):
config = json.load(open('./config.json', 'r'))
client = MongoClient(config['mongo_host'], config['mongo_port'])
diff --git a/app/models/user.py b/app_fb/models/user.py
similarity index 64%
rename from app/models/user.py
rename to app_fb/models/user.py
index 1df9f4f..eb8760b 100644
--- a/app/models/user.py
+++ b/app_fb/models/user.py
@@ -5,14 +5,25 @@ import json
class User:
- def __init__(self, name, email, username, password):
- self.name = name
- self.email = email
+ def __init__(self, username, password, posts, notifications, first_name, last_name, email, gender, locale, phone, address, friends, status, messages, image_url):
self.username = username
self.password = password
+ self.posts = posts
+ self.notifications = notifications
+ self.first_name = first_name
+ self.last_name = last_name
+ self.email = email
+ self.gender = gender
+ self.locale = locale
+ self.phone = phone
+ self.address = address
+ self.friends = friends
+ self.status = status
+ self.messages = messages
+ self.image_url = image_url
-class MongoUser:
+class MongoUserDao:
def __init__(self):
config = json.load(open('./config.json', 'r'))
client = MongoClient(config['mongo_host'], config['mongo_port'])
@@ -22,7 +33,7 @@ class MongoUser:
self.db.users.insert_one(user)
def search_by_name(self, name):
- result_cursor = self.db.users.find({'name': name})
+ result_cursor = self.db.users.find({'first_name': name})
matches = []
for user in result_cursor:
matches.append(user)
@@ -35,6 +46,8 @@ class MongoUser:
self.db.users.update_one({'_id': ObjectId(_id)}, {'$set': user})
def authenticate(self, user):
+ if user.username is None or user.password is None:
+ return False
result_cursor = self.db.users.find({'username': user.username, 'password':user.password})
if result_cursor.count() == 0:
return False
@@ -47,10 +60,19 @@ class MongoUser:
def add_stuff(self):
for i in range(10):
user = dict()
- user['name'] = "name" + str(i)
+
+ user['first_name'] = "first_name" + str(i)
+ user['last_name'] = "last_name" + str(i)
user['email'] = "email" + str(i)
+ if i % 2 == 0:
+ user['gender'] = 'Male'
+ user['locale'] = 'en-IN'
+ else:
+ user['gender'] = 'Female'
+ user['locale'] = 'en-US'
user['username'] = "username" + str(i)
user['password'] = "password" + str(i)
+ user['image_url'] = '/app/images/image' + str(i) + '.png'
self.db.users.insert_one(user)
def find_user_name_by_credentials(self, user):
@@ -59,7 +81,7 @@ class MongoUser:
matches = []
for user in result_cursor:
matches.append(user)
- return matches[0]['name'] if len(matches) > 0 else None
+ return matches[0]['first_name'] + " " + matches[0]['last_name'] if len(matches) > 0 else None
def check_if_user_exists(self, username):
result_cursor = self.db.users.find({'username': username})
@@ -109,4 +131,21 @@ class MongoUser:
user = self.get_by_id(user_id)
return user['cart']
+ def add_user_post(self, post, _id):
+ user = self.get_by_id(_id)
+ if user is not None:
+ if 'posts' in user:
+ user['posts'].append(post)
+ else:
+ posts = []
+ posts.append(post)
+ user['posts'] = posts
+ self.db.users.update_one({'_id': ObjectId(_id)}, {'$set': user})
+
+ def get_user_posts(self, _id):
+ user = self.get_by_id(_id)
+ if 'posts' in user:
+ return user['posts']
+ else:
+ return None
diff --git a/app/static/admin.html b/app_fb/static/admin.html
similarity index 100%
rename from app/static/admin.html
rename to app_fb/static/admin.html
diff --git a/app/static/blocks.css b/app_fb/static/blocks.css
similarity index 100%
rename from app/static/blocks.css
rename to app_fb/static/blocks.css
diff --git a/app_fb/static/images/image.png b/app_fb/static/images/image.png
new file mode 100644
index 0000000000000000000000000000000000000000..22392090a7c2b80641f922dd796693a85d8c005d
GIT binary patch
literal 104327
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
-%>
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