Commit 8fe0bbcd381cb883f9c885dff889481b10ab1e73

Lots of refactor, editing sweet and few more functionality

  - Refactor views to abstract a lot of logic to models
  - API for editing sweet
  - Permalink(non-API) to see a specific sweet
  - Frontend async code to edit sweets. (It would be better, IMO, if we can
    make the frontend of swtstore a separate app).
  - Change few APIs to be better. (Like previously to list a user's apps or
    contexts; one would go to /apps or /contexts; now it is /users/me/apps and
/users/me/contexts, also added /users/me/sweets).
  - Move a lot of debug print statements to a logger component.
  
1919# Run the server if this script is directly executed
2020# Presumably, this is development mode
2121if __name__ == '__main__':
22 app.run(debug=True, host='0.0.0.0', port=5001)
22 app.run(host='0.0.0.0', port=5001)
  
55
66from flask import Flask, request, jsonify, render_template, make_response, g
77import os
8import logging
89
910from classes.database import db
1011from config import DefaultConfig
2222 (views.api, '/api'),
2323 (views.user, '/users'),
2424 (views.context, '/contexts'),
25 (views.sweet, '/sweets'),
2526 (views.app, '/apps'),
2627 (views.Oauth, '/oauth')
2728)
150150
151151
152152def configure_logging(app):
153 #TODO: implement
154 pass
153
154 formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s '
155 '[in %(pathname)s:%(lineno)d]')
156
157 # TODO: maybe we can use a RotatingFileHandler?
158 # Also error can be sent out via email. So we can also have a SMTPHandler?
159 log_handler = logging.StreamHandler()
160
161 if app.config.has_key('LOG_LEVEL'):
162 log_level = app.config['LOG_LEVEL'] or 'ERROR'
163 else:
164 log_level = 'ERROR'
165
166 log_handler.setLevel(log_level)
167 log_handler.setFormatter(formatter)
168
169 app.logger.addHandler(log_handler)
  
55
66class AlreadyExistsError(Exception, DontWrapMixin):
77 pass
8
9class InvalidPayload(Exception, DontWrapMixin):
10 pass
  
33# class:: Client
44
55from datetime import datetime, timedelta
6from flask import current_app
67
78from swtstore.classes.database import db
89from swtstore.classes.models.um import User
157157
158158@oauth.clientgetter
159159def loadClient(client_id):
160 print '@oauth.clientgetter'
160 current_app.logger.debug('@oauth.clientgetter')
161161 #return Client.query.filter_by(id=client_id).first()
162162 return Client.query.get(client_id)
163163
164164@oauth.grantgetter
165165def loadGrant(client_id, code):
166 print '@oauth.grantgetter'
166 current_app.logger.debug('@oauth.grantgetter')
167167 return Grant.query.filter_by(client_id=client_id, code=code).first()
168168
169169@oauth.grantsetter
170170def saveGrant(client_id, code, request, *args, **kwargs):
171 print '@oauth.grantsetter'
171 current_app.logger.debug('@oauth.grantsetter')
172172 expires = datetime.utcnow() + timedelta(seconds=100)
173173 grant = Grant(
174174 client_id = client_id,
184184
185185@oauth.tokengetter
186186def loadToken(access_token=None, refresh_token=None):
187 print '@oauth.tokengetter'
187 current_app.logger.debug('@oauth.tokengetter')
188188 if access_token:
189189 return Token.query.filter_by(access_token=access_token).first()
190190 elif refresh_token:
192192
193193@oauth.tokensetter
194194def saveToken(token, request, *args, **kwargs):
195 print '@oauth.tokensetter'
195 current_app.logger.debug('@oauth.tokensetter')
196196
197197 toks = Token.query.filter_by(client_id=request.client.id,
198198 user_id=request.user.id)
  
5858
5959 # return a context instance given a name
6060 @staticmethod
61 def getContextByName(name):
61 def getByName(name):
6262 return Context.query.filter_by(name=name).first()
6363
6464 @staticmethod
  
22# classes/sweet.py
33# class:: Sweet
44
5from flask import current_app
56from datetime import datetime
67
78from swtstore.classes.database import db
89# custom SQLAlchemy type JSONType
910from swtstore.classes.models.types import JSONType
1011from swtstore.classes.utils import urlnorm # normalize URLs
12from swtstore.classes.models import Context
13from swtstore.classes.models.um import User
1114
1215class Sweet(db.Model):
1316 """ customary docstring """
3333
3434
3535 def __init__(self, who, what, where, how):
36 print 'initing sweet..'
36 current_app.logger.info('initing sweet..')
3737 self.who = who
3838 self.what = what
3939 self.where = urlnorm(where)
4848 return '[Sweet Object: <%s : @%s: #%s : %s>]' % (self.id, self.who,
4949 self.what, self.where)
5050
51 # Update the sweet - only 'how' and 'where' fields can be updated
52 def update(self, **kwargs):
53 if kwargs.get('how'):
54 self.how = kwargs.get('how')
55 self.persist()
56 if kwargs.get('where'):
57 self.where = kwargs.get('where')
58 self.persist()
59
60 return None
61
62
63 # create multiple sweets from a list of JSON
64 @staticmethod
65 def createSweets(who, payload):
66 # the payload has to be a list; a list of swts
67 for each in payload:
68 if 'what' not in each and 'where' not in\
69 each and 'how' not in each:
70
71 raise InvalidPayload('Invalid payload %s \n for creating\
72 mutiple sweets' % (each))
73 return None
74
75 # all ok. create swts from the list now
76 swts = []
77 for each in payload:
78
79 what = Context.getByName(each['what'])
80
81 if what is None:
82 current_app.logger.info('Context "%s" do not exist. Aborting',
83 what)
84 g.error = 'Context do not exist'
85 abort(400) # this context doesn't exist!
86
87 current_app.logger.debug('SWEET PAYLOAD\n---\n%s\n%s\n%s\n%s\n----',
88 who, what, each['where'], each['how'])
89
90 new_sweet = Sweet(who, what, each['where'], each['how'])
91
92 new_sweet.persist()
93 current_app.logger.debug('New Sweet %s', new_sweet)
94 swts.append(new_sweet)
95
96 return swts
97
98 # get Sweets for frontend
99 @staticmethod
100 def getFrontendSwts():
101 return Sweet.query.order_by(Sweet.created.desc()).all()
102
103 # get sweets all sweets authored by a particular user
104 @staticmethod
105 def getByCreator(user):
106 return Sweet.query.filter_by(who=user).\
107 order_by(Sweet.created.desc()).all()
108
109 # allow to query all sweets based on "who", "what" and "where" params
110 @staticmethod
111 def queryByAll(params):
112 if params.get('who'):
113 params['who'] = User.getByName(params['who'])
114 if params.get('what'):
115 params['what'] = Context.getByName(params['what'])
116
117 return Sweet.query.filter_by(**params).all()
118
51119 # return a dictionary of data members
52120 def to_dict(self):
53 print self.created
54121 return {
55122 'id': self.id,
56123 'who': self.who.username,
133133 # create and persist the sweet to the database
134134 def persist(self):
135135
136 current_app.logger.debug('Commiting sweet %s to db', self)
136137 db.session.add(self)
137138 db.session.commit()
  
33 __init__.py
44"""
55from urlnorm import urlnorm
6from httputils import makeCORSHeaders
  
1# HTTP utilities
2from flask import current_app
13
2
3def make_cross_origin_headers(response, host_url):
4 print 'client\'s host_url: %s' % host_url
4def makeCORSHeaders(response, host_url):
5 current_app.logger.debug('makeCORSHeaders(): client\'s host_url: %s',
6 host_url)
57 response.headers['Access-Control-Allow-Origin'] = host_url
68 response.headers['Access-Control-Max-Age'] = '3600'
79 response.headers['Access-Control-Allow-Credentials'] = 'true'
810 response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'
911
10 print 'Updated headers'
11 print response.headers
12 current_app.logger.debug('Updated headers %s', response.headers)
1213
1314 return response
15
16from datetime import timedelta
17from flask import make_response, request, current_app
18from functools import update_wrapper
19
20"""
21def crossdomain(origin=None, methods=None, headers=None, max_age=3600,
22 attach_to_all=True, automatic_options=True):
23
24 if methods is not None:
25 methods = ', '.join(sorted(i.upper() for i in methods))
26 if headers in not None and not isinstance(headers, basestring):
27 headers = ', '.join(i.upper() for i in headers)
28 if not isinstance(origin, basestring):
29 origin = ', '.join(origin)
30 if isinstance(max_age, timedelta):
31 max_age = max_age.total_seconds()
32
33 def get_methods():
34 if methods is not None:
35 return methods
36
37 options_resp = current
38
39"""
  
22from .api import api
33from .user import user
44from .context import context
5from .sweet import sweet
56from .app import app
67from .oauth import Oauth
  
1from flask import Module, jsonify, request, make_response, abort, g, json
2#import json
3from sqlalchemy.exc import IntegrityError
1from flask import Module, jsonify, request, make_response, abort, g, json,\
2 current_app
43
54from swtstore.classes.models import Context
65from swtstore.classes.models import Sweet
7from swtstore.classes.exceptions import AlreadyExistsError
6from swtstore.classes.exceptions import AlreadyExistsError, InvalidPayload
87from swtstore.classes.utils import urlnorm # normalize URLs
9from swtstore.classes.utils.httputils import make_cross_origin_headers
8from swtstore.classes.utils.httputils import makeCORSHeaders
109from swtstore.classes import oauth
1110
1211
1313
1414
1515# Get a specific sweet
16@api.route('/sweets/<int:id>', methods=['GET'])
16# Update a specific sweet
17@api.route('/sweets/<int:id>', methods=['GET', 'PUT'])
1718def getSweetById(id):
18 try:
19
20 # Get a specific sweet
21 if request.method == 'GET':
1922 sweet = Sweet.query.get(id)
20 except:
21 abort(404)
2223
23 if sweet is None:
24 abort(404)
24 if sweet is None:
25 abort(404)
2526
26 print sweet
27 return jsonify(sweet.to_dict())
27 current_app.logger.debug('getSweetById: %s', sweet)
28 return jsonify(sweet.to_dict())
2829
30 # Update a specific sweet
31 elif request.method == 'PUT':
32 payload = request.json
33 if payload is None:
34 abort(400)
2935
36 current_app.logger.debug('Update Sweet: recvd payload: %s', payload)
37
38 sweet = Sweet.query.get(id)
39
40 if sweet is None:
41 abort(404)
42
43 current_app.logger.debug('Updating sweet %s with new how: %s ',
44 sweet.id, payload)
45
46 sweet.update(how=payload)
47
48 return jsonify(sweet.to_dict())
49
50
3051# Post a sweet to the sweet store
3152@api.route('/sweets', methods=['OPTIONS', 'POST'])
3253@oauth.require_oauth('email', 'sweet')
5757
5858 client = oauth_request.client
5959
60 #TODO: check if response is coming from a registered client
61 response = make_cross_origin_headers(response, client.host_url)
60 #TODO: make a decorator of CORS request
61 response = makeCORSHeaders(response, client.host_url)
6262
6363 if request.method == 'OPTIONS':
6464 response.status_code = 200
6565 return response
6666
67 if request.json:
68 payload = request.json
69 if request.data:
70 payload = json.loads(request.data)
71 else:
72 print 'data not found in payload!'
67 payload = request.json or request.data
68 if not payload:
69 current_app.logger.error('data not found in payload!')
7370 g.error= 'data not found in payload!'
7471 abort(400)
7572
76 print 'new sweet payload recvd..'
77 print payload
73 current_app.logger.debug('new sweet payload recvd.. %s', payload)
7874
79 # the payload has to be a list; a list of swts
80 for each in payload:
81 if 'what' not in each and 'where' not in\
82 each and 'how' not in each:
75 # Get the authenticated user from the oauth request object.
76 # Older swtr clients sending `who` in string will be ignored.
77 who = oauth_request.user
8378
84 print 'Invalid Request..'
85 abort(400)
79 try:
80 swts = Sweet.createSweets(who, payload)
81 except InvalidPayload(msg):
82 current_app.logger.error('Invalid Payload in request')
83 abort(400)
8684
87 # all ok. create swts from the list now
88
89 swts = []
90 for each in payload:
91
92 what = Context.query.filter_by(name=each['what']).first()
93
94 if what is None:
95 print 'Context doesn\'t exist'
96 g.error = 'Context doesn\'t exist'
97 abort(400) # this context doesn't exist!
98
99 # Get the authenticated user from the oauth request object.
100 # Older swtr clients sending `who` in string will be ignored.
101 who = oauth_request.user
102
103 print 'SWEET DATA'
104 print '------------'
105 print who
106 print what
107 print each['where']
108 print each['how']
109 print '-------------'
110
111 new_sweet = Sweet(who, what, each['where'], each['how'])
112
113 new_sweet.persist()
114 print new_sweet
115 swts.append(new_sweet.id)
116
11785 response.status_code = 200
118 response.data = json.dumps(swts)
86 response.headers['Content-type'] = 'application/json'
87 response.data = json.dumps([i.to_dict() for i in swts])
11988 return response
12089
12190
12291# The Sweet query API: /sweets/q?who=<>&what=<>&where=<>
12392# args: who, what, where
12493@api.route('/sweets/q', methods=['GET', 'OPTIONS'])
125@oauth.require_oauth('sweet')
126def querySweets(oauth_request):
94#@oauth.require_oauth('sweet')
95def querySweets():
12796
12897 response = make_response()
129 response = make_cross_origin_headers(response,
130 oauth_request.client.host_url)
98 origin = request.headers.get('Origin', '*')
99 response = makeCORSHeaders(response, origin)
131100
132101 if request.method == 'OPTIONS':
133102 reponse.status_code = 200
112112 if args.get('who'):
113113 params['who'] = args.get('who')
114114 if args.get('what'):
115 what = Context.query.filter_by(name=args.get('what')).first()
116 params['what'] = what
115 params['what'] = args.get('what')
117116 if args.get('where'):
118117 params['where'] = urlnorm(args.get('where'))
119118
120120 if len(params) == 0:
121121 abort(400)
122122
123 print 'recvd params'
124 print params
123 current_app.logger.debug('recvd params: %s', params)
125124
125 sweets = Sweet.queryByAll(params)
126126
127 sweets = Sweet.query.filter_by(**params).all()
128
129127 if len(sweets) == 0:
130 print 'No sweets found to satisfy query..'
128 current_app.logger.info('No sweets found to satisfy query..')
131129 abort(404)
132130
133131 swts = [i.to_dict() for i in sweets]
139139@api.route('/contexts/<name>', methods=['GET'])
140140def getContextByName(name):
141141
142 context = Context.query.filter_by(name=name).first()
142 context = Context.getByName(name)
143143 if context is None:
144144 abort(404)
145145
146 print context
146 current_app.logger.debug('getContextByName : %s', context)
147147 return jsonify(context.to_dict())
148148
149149# Get a specific context with its definition; based on id
154154 if context is None:
155155 abort(404)
156156
157 print context
158 print context.created
159 print context.to_dict()
160 print jsonify(context.to_dict()).data
157 current_app.logger.debug('getContextById response: %s',
158 jsonify(context.to_dict()).data)
159
161160 return jsonify(context.to_dict())
162161
163162
176176 # if not found send back a 400
177177 abort(400)
178178
179 #TODO: change it to logger component
180 print 'new context payload recvd..'
181 print payload
179 current_app.logger.debug('new context payload recvd.. %s', payload)
182180
183181 # if data is invalid send back 400
184182 if 'name' not in payload and 'definition' not in payload:
187187
188188 except AlreadyExistsError:
189189 # context with same name exists; send back 400?
190 print 'Already Exists Error'
190 current_app.logger.info('Context Already Exists Error')
191191 abort(400)
192192
193 print 'new context'
194 print new_context
193 current_app.logger.debug('new context created: %s', new_context)
194
195195 # all ok. save the new context
196196 res = new_context.persist()
197197
204204@oauth.require_oauth('email')
205205def getCurrentUser(oauth_request):
206206 response = make_response()
207 response = make_cross_origin_headers(response,
208 oauth_request.client.host_url)
207 response = makeCORSHeaders(response, oauth_request.client.host_url)
209208 response.status_code = 200
210209
211210 if request.method == 'OPTIONS':
212211 return response
213212
213 response.headers['Content-type'] = 'application/json'
214 # We have the user object along with the oauth request. Just return it back
214215 response.data = json.dumps(oauth_request.user.to_dict())
215216 return response
  
1
21# -*- coding utf-8 -*-
32# classes/views/apps.py
43
5
64from flask import Module, jsonify, request, render_template, redirect,\
75 url_for, flash, abort
86
1414
1515app = Module(__name__)
1616
17@app.route('/', methods=['GET'])
18# list apps owned by current user
19def list():
20 current_user = User.getCurrentUser()
21 if current_user is None:
22 return redirect(url_for('frontend.index'))
2317
24 her_apps = Client.getClientsByCreator(current_user.id)
25 print 'her_apps'
26 print her_apps
27 return render_template('list_apps.html', apps=her_apps,
28 user=current_user.to_dict())
29
30
3118@app.route('/register', methods=['GET', 'POST'])
3219def register():
3320 current_user = User.getCurrentUser()
3421 if current_user is None:
3522 return redirect(url_for('frontend.index'))
3623
37 user = current_user.to_dict()
38
3924 if request.method == 'GET':
40 return render_template('register_app.html', user=user)
25 return render_template('register_app.html')
4126
4227 elif request.method == 'POST':
4328 req_fields = ['name', 'host_url', 'redirect_uris', 'scopes']
4343 )
4444 new_app.persist()
4545
46 return redirect(url_for('list'))
46 return redirect(url_for('user.myApps'))
  
1
21# -*- coding utf-8 -*-
32# classes/views/context.py
43
4from flask import Module, jsonify, request, render_template, redirect,\
5 url_for, json, current_app
56
6from flask import Module, jsonify, request, render_template, redirect, url_for
7import json
8
97from swtstore.classes.models import Context
108from swtstore.classes.models.um import User
119
1210
1311context = Module(__name__)
1412
15@context.route('/', methods=['GET'])
16# list apps owned by current user
17def list():
18 current_user = User.getCurrentUser()
19 if current_user is None:
20 return redirect(url_for('index'))
21
22 her_contexts = Context.getByCreator(current_user.id)
23 print 'her_apps'
24 print her_contexts
25
26 return render_template('list_contexts.html', contexts=her_contexts,
27 user=current_user.to_dict())
28
29
3013@context.route('/register', methods=['GET', 'POST'])
3114def register():
3215 current_user = User.getCurrentUser()
3316 if current_user is None:
34 return redirect(url_for('index'))
17 return redirect(url_for('frontend.index'))
3518
36 user = current_user.to_dict()
37
3819 if request.method == 'GET':
39 return render_template('register_context.html', user=user)
20 return render_template('register_context.html')
4021
4122 if request.method == 'POST':
4223 if not request.form.get('name') or not request.form.get('defn'):
4324 abort(400)
4425
45 print request.form.get('defn')
26 current_app.logger.debug('New Context: defn: %s ',
27 request.form.get('defn'))
4628 json_ld = json.loads(request.form.get('defn'))
47 print json_ld
29 current_app.logger.debug('Resulting json_ld %s', json_ld)
4830
4931 new_context = Context(
5032 name = request.form.get('name'),
5133 definition = json_ld,
5234 user_id = current_user.id
5335 )
54 print new_context
36 current_app.logger.debug('New Context created: %s', new_context)
5537 new_context.persist()
5638
57 return redirect(url_for('list'))
39 return redirect(url_for('user.myContexts'))
  
22# classes/views/frontend.py
33
44
5from flask import Module, jsonify, request, render_template, redirect, url_for
5from flask import Module, jsonify, request, render_template, redirect,\
6 url_for, g, current_app
67
8from sqlalchemy import desc
9
710from swtstore.classes.models import Sweet
811from swtstore.classes.models.um import User
912
1515
1616@frontend.route('/', methods=['GET'])
1717def index():
18 # sweets = Sweet.query.somethingToGetRelevant()
19 sweets = Sweet.query.all()
18 sweets = Sweet.getFrontendSwts()
2019
2120 user = User.getCurrentUser()
22 if user is not None:
23 user = user.to_dict()
2421
25 return render_template('index.html', sweets=sweets, user=user)
22 return render_template('index.html', sweets=sweets)
2623
2724
2825# Create a new sweet context
  
11# -*- coding utf-8 -*-
22# classes/views/oauth.py
33
4from flask import Module, jsonify, request, render_template, redirect, url_for
5import json
4from flask import Module, jsonify, request, render_template, redirect,\
5 url_for, current_app
66
77from swtstore.classes import oauth
88from swtstore.classes.models.um import User
2121 if request.method == 'GET':
2222 client_id = kwargs.get('client_id')
2323 client = Client.query.get(client_id)
24 print '/authorize: '
25 print client
24 current_app.logger.debug('In /authorize: client: %s', client)
2625 kwargs['client'] = client
2726 kwargs['user'] = current_user
28 print kwargs
27 current_app.logger.debug('kwargs %s', kwargs)
2928 return render_template('authorize.html', **kwargs)
3029
3130 confirm = request.form.get('confirm', 'no')
32 print confirm
31 current_app.logger.debug('confirm authorize from user: %s', confirm)
3332 return confirm == 'yes'
3433
3534@Oauth.route('/token', methods=['GET', 'POST'])
3635@oauth.token_handler
3736def access_token():
3837 #print request.form
39 print 'access token touched..'
38 current_app.logger.debug('access token touched..')
4039 return None
4140
4241@Oauth.route('/errors')
  
1# -*- coding utf-8 -*-
2# classes/views/sweet.py
3
4
5from flask import Module, jsonify, request, render_template, redirect,\
6 url_for, abort, json
7
8from swtstore.classes.models import Context
9from swtstore.classes.models import Sweet
10from swtstore.classes.models.um import User
11
12
13sweet = Module(__name__)
14
15@sweet.route('/<id>', methods=['GET'])
16def showSweet(id):
17 #current_user = User.getCurrentUser()
18 #if current_user is None:
19 # return redirect(url_for('index'))
20
21 #user = current_user.to_dict()
22 print "recvd sweet id: %s" % (id)
23 sweet = Sweet.query.get(id)
24 if sweet:
25 print "sweet found " + str(sweet)
26 return render_template('specific_sweet.html', sweet=sweet)
27 else:
28 abort(404)
  
33
44import requests
55
6# flask imports
67from flask import Module, jsonify, request, render_template, session,\
7 make_response, url_for, redirect
8import json
8 make_response, url_for, redirect, json, current_app
99
10# swtstore imports
1011from swtstore.classes.models.um import User
12from swtstore.classes.models import Sweet, Context, Client
1113
12from swtstore.classes.utils.httputils import make_cross_origin_headers
14from swtstore.classes.utils.httputils import makeCORSHeaders
1315from swtstore.config import DefaultConfig
1416
1517
2323def login():
2424
2525 response = make_response()
26 #response = make_cross_origin_headers(response)
26 #response = makeCORSHeaders(response)
2727
2828 if 'assertion' not in request.form:
2929 response.status_code = 400
3030 return response
3131
32 print request.remote_addr
32 current_app.logger.debug('remote address of request for user login %s',
33 request.remote_addr)
34
3335 data = {'assertion': request.form['assertion'], 'audience':
3436 config.SWTSTORE_URL}
3537
3638 resp = requests.post(config.MOZ_PERSONA_VERIFIER, data=data, verify=True)
37 print resp.status_code
38 print resp.json()
39 current_app.logger.debug('Response code from MOZ_PERSONA_VERIFIER %s',
40 resp.status_code)
41 current_app.logger.debug('Response body: %s', resp.json())
3942
4043 if resp.ok:
4144 verified_data = json.loads(resp.content)
4848 current_user = User.query.filter_by(email=user_email).first()
4949 # user doesn't exist; create her
5050 if current_user is None:
51 print 'user with email ' + user_email + ' doesn\'t exist;'
52 print 'creating new user:' + user_email
51 current_app.logger.info('user with email %s doesn\'t exist',
52 user_email)
53 current_app.logger.info('creating new user: %s', user_email)
54
5355 new_user = User('', user_email)
5456 new_user.persist()
5557 current_user = new_user
5658
5759 #session.update({'email': verified_data['email']})
58 print 'logging in user with email' + user_email
60 current_app.logger.info('logging in user with email %s',
61 user_email)
5962 session['email'] = current_user.email
6063
6164 response.status_code = 200
7272def logout():
7373
7474 response = make_response()
75 #response = make_cross_origin_headers(response)
75 #response = makeCORSHeaders(response)
7676
7777 if 'email' in session:
78 print 'logging out '
79 print session['email']
78 current_app.logger.info('logging out user %s', session['email'])
8079 session.pop('email')
8180
8281 response.status_code = 200
9292 return render_template('me.html', user=current_user)
9393
9494 username = request.form.get('username')
95 print username
95
96 current_app.logger.debug('Updating username of %s to %s',
97 current_user.username, username)
98
9699 current_user.update(username=username)
97100
98101 return redirect(url_for('profile'))
102
103
104@user.route('/me/sweets', methods=['GET'])
105def mySweets():
106
107 user = User.getCurrentUser()
108 if user is None:
109 return redirect(url_for('frontend.index'))
110
111 swts = Sweet.getByCreator(user)
112 return render_template('my_sweets.html', sweets=swts)
113
114
115@user.route('/me/contexts', methods=['GET'])
116def myContexts():
117
118 user = User.getCurrentUser()
119 if user is None:
120 return redirect(url_for('frontend.index'))
121
122 contexts = Context.getByCreator(user.id)
123 return render_template('my_contexts.html', contexts=contexts)
124
125
126@user.route('/me/apps', methods=['GET'])
127def myApps():
128
129 # make a decorator out of this repetative code
130 user = User.getCurrentUser()
131 if user is None:
132 return redirect(url_for('frontend.index'))
133
134 apps = Client.getClientsByCreator(user.id)
135 return render_template('my_apps.html', apps=apps)
  
55 this.attachLogout();
66 this.initPersona();
77 this.activeNav();
8 $('.edit-sweet').click(ss.editSweet);
89 };
910
1011 ss.activeNav = function() {
6969 });
7070 }
7171 });
72 };
73
74 ss.editSweet = function(event) {
75 var target = $(event.currentTarget).attr('for');
76 var how = JSON.parse($(event.currentTarget).siblings('.how').html());
77 //console.log(how);
78 // update sweet function
79 function updateSweet(event) {
80 var changed = false;
81 for(var field in how) {
82 var data = $('#edit-sweet-modal .modal-body textarea[name="'+field+'"]').val();
83 var item = (typeof how[field] === 'object') ? JSON.stringify(how[field]) :
84 how[field];
85 if(data !== item) {
86 changed = true;
87 how[field] = data;
88 console.log('Updated '+ field + ' with data: ', data);
89 }
90 }
91 if(changed) {
92 $('#save-edited-sweet').text('Saving Changes');
93
94 $.ajax({
95 type: 'PUT',
96 url: 'http://localhost:5001/api/sweets/'+target,
97 contentType: 'application/json',
98 data: JSON.stringify(how),
99 success: function(data) {
100 console.log('Updated swt from the server ', data);
101 $('#save-edited-sweet').text('Save Changes');
102 $('#edit-sweet-modal').modal('hide');
103 },
104 error: function() {
105 $('#save-edited-sweet').text('Save Changes');
106 }
107 });
108 }
109 else {
110 return;
111 }
112 }
113 // prepare the edit view
114 $('#edit-sweet-modal .modal-body').html('');
115 for(var field in how) {
116 var item = (typeof how[field] === 'object') ? JSON.stringify(how[field]) :
117 how[field];
118
119 $('#edit-sweet-modal .modal-body').append('<div class="form-group"> <b>'+
120 field+'</b>');
121 /*$('<input>',
122 {name: field, value: item, class: 'form-control', type: 'text'}).
123 appendTo('#edit-sweet-modal .modal-body');*/
124 $('#edit-sweet-modal .modal-body').append('<textarea name="'+field+'" class="form-control">'+item+'</textarea>');
125
126 $('#edit-sweet-modal').append('</div>');
127 }
128 // launch the modal
129 $('#edit-sweet-modal').modal();
130
131 // attach event handlers
132 $('#save-edited-sweet').off('click');
133 $('#save-edited-sweet').on('click', updateSweet);
134
72135 };
73136
74137})(ss);
  
2828 <small><i>created: {{sweet.created }}</i></small>
2929
3030 <span class="pull-right permalink">
31 <a href="#">
31 <a href="{{ url_for('sweet.showSweet', id=sweet.id) }}">
3232 <i class="glyphicon glyphicon-share"></i>
3333 </a>
3434 </li>
  
1717 <li>
1818 <a href="{{ url_for('frontend.index') }}"> Home </a>
1919 </li>
20 {% if not user %}
20 {% if not session.email %}
2121 <li>
2222 <a id="login" href="#"> Login </a>
2323 </li>
2424 {% else %}
25 <!-- swts list -->
26 <li>
27 <a href="{{ url_for('user.mySweets') }}"> My Sweets </a>
28 </li>
2529 <!-- the cog menu -->
2630 <li class="dropdown user-menu">
2731 <a class="dropdown-toggle" data-toggle="dropdown" href="#">
3333 </a>
3434 <ul class="dropdown-menu" role="menu">
3535 <li> <a href="{{ url_for('app.register') }}">Register New App</a> </li>
36 <li> <a href="{{ url_for('app.list') }}">Registered Apps</a> </li>
36 <li> <a href="{{ url_for('user.myApps') }}">Registered Apps</a> </li>
3737 <li class="divider"></li>
3838 <li> <a href="{{ url_for('context.register') }}">Register New Context</a> </li>
39 <li> <a href="{{ url_for('context.list') }}">Registered Contexts</a> </li>
39 <li> <a href="{{ url_for('user.myContexts') }}">Registered Contexts</a> </li>
4040 </ul>
4141 </li>
4242 <!-- the user menu -->
4848 <ul class="dropdown-menu" role="menu">
4949 <li>
5050 <a href="{{ url_for('user.profile') }}"><small>
51 {% if user.username %}
52 {{ user.username }}
53 {% else %}
54 {{ user.email }}
55 {% endif %}
51 {{ session.email }}
5652 </small></a>
5753 </li>
5854 <li class="divider"></li>
8585 ss.loginURL = function() { return "{{ url_for('user.login') }}"; };
8686 ss.logoutURL = function() { return "{{ url_for('user.logout') }}"; };
8787 ss.loggedInUser = function() {
88 {% if not user %}
89 var user = '';
90 {% else %}
91 var user = "{{ user.email }}";
92 {% endif %}
93 if(user) {
94 return user;
95 }
96 return null;
88 return ("{{ session.email }}") ? "{{ session.email }}" : null;
9789 };
9890 window.onload = function() {
9991 ss.init();
  
1{% extends "layout.html" %}
2{% block body %}
3<div>
4 {% if apps|length > 0 %}
5 <ul>
6 {% for app in apps %}
7 <div class="well">
8 <div class="pull-right">
9 <span class="glyphicon glyphicon-trash"></span>
10 </div>
11 <div><h4> {{ app.name }} </h4></div>
12 <div><h5> {{ app.description }} </h5></div>
13 <div>APP ID: {{ app.id }} </div>
14 <div> APP Secret: {{ app.client_secret }} </div>
15 <div>Host URL: {{ app.host_url }} </div>
16 <div>Redirect URL: {{ app.redirect_uris|join(', ') }} </div>
17 <div>Scopes: {{ app.default_scopes|join(', ') }} </div>
18 </div>
19 {% endfor %}
20 </ul>
21 {% else %}
22 <em> You haven't registered any apps yet! </em>
23 {% endif %}
24</div>
25{% endblock %}
  
1{% extends "layout.html" %}
2{% block body %}
3<div>
4 {% if contexts|length > 0 %}
5 <ul>
6 {% for context in contexts %}
7 <div class="well">
8 <div class="pull-right">
9 <span class="glyphicon glyphicon-trash"></span>
10 </div>
11 <div> {{ context.name }} </div>
12 <div> {{ context.definition }} </div>
13 </div>
14 {% endfor %}
15 </ul>
16 {% else %}
17 <em> You haven't registered any contexts yet! </em>
18 {% endif %}
19</div>
20{% endblock %}
  
1{% extends "layout.html" %}
2
3{% block body %}
4
5 {% if sweets|length > 0 %}
6
7 <ul class="entries unstyled">
8 {% for sweet in sweets %}
9 <li>
10 <span class="who">
11 <a href="#">
12 @{{ sweet.who.username }}
13 </a>
14 </span>
15 <span class="what">
16 <b> #{{ sweet.what.name }} </b>
17 </span>
18 <span class="where">
19 {{ sweet.where }}
20 </span>
21 <p></p>
22 <span class="how">
23 {{ sweet.how|tojson }}
24 </span>
25
26 <small><i>created: {{sweet.created }}</i></small>
27
28 <span class="pull-right permalink">
29 <a href="#">
30 <i class="glyphicon glyphicon-share"></i>
31 </a>
32 </span>
33 <span class="pull-right edit-sweet" for="{{ sweet.id }}">
34 <a href="#">
35 <i class="glyphicon glyphicon-edit"></i>
36 </a>
37 </span>
38 </li>
39 {% endfor %}
40 </ul>
41
42 {% else %}
43 <div class="row">
44 <div class="col-md-5">
45 <h4><em>Unbelievable! No sweets yet!!</em></h4>
46 </div>
47 </div>
48 {% endif %}
49
50 <div class="modal fade" id="edit-sweet-modal">
51 <div class="modal-dialog">
52 <div class="modal-content">
53 <div class="modal-header">
54 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
55 <h4 class="modal-title">Edit Sweet </h4>
56 </div>
57 <div class="modal-body"></div>
58 <div
59 class="modal-footer">
60 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
61 <button type="button" class="btn btn-primary" id="save-edited-sweet">Save changes</button>
62 </div>
63 </div><!-- /.modal-content -->
64 </div><!-- /.modal-dialog -->
65 </div><!-- /.modal -->
66
67{% endblock %}
  
1{% extends "layout.html" %}
2
3{% block body %}
4
5<ul class="entries unstyled">
6 <li>
7 <span class="who">
8 <a href="#">
9 @{{ sweet.who.username }}
10 </a>
11 </span>
12 <span class="what">
13 <b> #{{ sweet.what.name }} </b>
14 </span>
15 <span class="where">
16 {{ sweet.where }}
17 </span>
18 <p></p>
19 <span class="how">
20 {{ sweet.how|escape|safe }}
21 </span>
22
23 <small><i>created: {{sweet.created }}</i></small>
24 </li>
25</ul>
26
27{% endblock %}