Skip to content

Commit 8fd545f

Browse files
committed
Resolve merge conflicts
2 parents a17ea9f + 0e2238e commit 8fd545f

File tree

10 files changed

+231
-29
lines changed

10 files changed

+231
-29
lines changed

Failures.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ def wrong_password(email):
178178
}, 401
179179

180180

181+
def password_unknown_format(fault_message):
182+
logging.debug('Failures: %s', fault_message)
183+
return {
184+
'success': False,
185+
'message': 'Unencoded Unicode password',
186+
'code': 475,
187+
'data': fault_message
188+
}, 500
189+
190+
181191
def unknown_bucket_type(bucket_type):
182192
logging.debug('Failures: Unknown bucket type: %s', bucket_type)
183193
return {
@@ -196,3 +206,4 @@ def wrong_auth_source(auth_source):
196206
'code': 480,
197207
'data': auth_source
198208
}, 500
209+

app/Authenticate/controllers.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,18 @@ def post(self):
7676
if not rate_limiting_services.has_sufficient_tokens(user.id, 'failed-password', 1):
7777
return Failures.rate_exceeded()
7878

79-
if not user_services.check_password(user.id, password):
80-
rate_limiting_services.consume_tokens(user.id, 'failed-password', 1)
81-
db.session.commit()
82-
return Failures.wrong_password(email)
79+
# The password might not be encoded correctly when submitted. This
80+
# could cause the check_password method to fault. We trap that
81+
# possibility and address it here.
82+
try:
83+
if not user_services.check_password(user.id, password):
84+
rate_limiting_services.consume_tokens(user.id, 'failed-password', 1)
85+
return Failures.wrong_password(email)
86+
except TypeError:
87+
return Failures.password_unknown_format("Unicode-objects must be encoded before hashing")
8388

8489
db.session.commit()
85-
8690
logging.info('Authenticate-controller: Authenticate: success: %s', email)
87-
8891
return {'success': True, 'user': {
8992
'id': user.id,
9093
'email': user.email,

app/Health/__init__.py

Whitespace-only changes.

app/Health/controllers.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# ------------------------------------------------------------------------------
2+
# Copyright (c) 2019 Parallax Inc. -
3+
# -
4+
# Permission is hereby granted, free of charge, to any person obtaining -
5+
# a copy of this software and associated documentation files (the -
6+
# “Software”), to deal in the Software without restriction, including -
7+
# without limitation the rights to use, copy, modify, merge, publish, -
8+
# distribute, sublicense, and/or sell copies of the Software, and to -
9+
# permit persons to whom the Software is furnished to do so, subject -
10+
# to the following conditions: -
11+
# -
12+
# The above copyright notice and this permission notice shall be -
13+
# included in all copies or substantial portions of the Software. -
14+
# -
15+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -
16+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -
17+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. -
18+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -
19+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -
20+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -
21+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -
22+
# -
23+
# -
24+
# ------------------------------------------------------------------------------
25+
26+
import logging
27+
from flask_restful import Api, Resource
28+
from flask import request, Blueprint
29+
from app import __version__
30+
31+
32+
# Set the base URL for this module and register it
33+
health_app = Blueprint('health', __name__, url_prefix='/health')
34+
api = Api(health_app)
35+
36+
37+
class Ping(Resource):
38+
# noinspection PyUnresolvedReferences
39+
"""
40+
Provide a simple response to verify that the Rest API is functioning.
41+
42+
Args:
43+
None
44+
45+
Returns:
46+
A JSON document with the key 'success' set to True, 'message' set to
47+
the constant 'pong', and a 200 response code.
48+
49+
Raises:
50+
None
51+
"""
52+
def get(self):
53+
# Ping the REST server for signs of life
54+
server = request.headers.get('server')
55+
logging.info("Requesting ping from server %s", server)
56+
57+
return {
58+
'Success': True,
59+
'message': 'pong',
60+
'code': 200
61+
}
62+
63+
64+
class Version(Resource):
65+
# noinspection PyUnresolvedReferences
66+
"""
67+
Provide the application version string.
68+
69+
Args:
70+
None
71+
72+
Returns:
73+
A JSON document with the key 'success' set to True, 'message' contains a
74+
version element holding a string representation of the application version
75+
number, and a 200 response code.
76+
77+
Raises:
78+
None
79+
"""
80+
def get(self):
81+
# Ping the REST server for signs of life
82+
server = request.headers.get('server')
83+
logging.info("Requesting version info from server %s", server)
84+
85+
return {
86+
'Success': True,
87+
'message': {
88+
'version': __version__.__version__,
89+
},
90+
'code': 200
91+
}
92+
93+
94+
api.add_resource(Ping, '/ping')
95+
api.add_resource(Version, '/version')

app/LocalUser/controllers.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import logging
2828

2929
import Failures
30-
from app import db, app
30+
from app import db
3131

3232

3333
from flask_restful import Resource, Api
@@ -43,22 +43,24 @@
4343

4444

4545
class DoConfirm(Resource):
46+
# noinspection PyUnresolvedReferences
4647
"""
47-
Confirm and activate a user account.
48+
Confirm and activate a user account.
4849
49-
Args:
50-
None
50+
Args:
51+
None
5152
52-
Returns:
53-
A JSON document with the key 'success' set to True if the operation
54-
is successful. Otherwise the key 'success' is set to False and the
55-
field 'code' is set to the HTTP error code that represents a specific
56-
reason when the account confirmation was rejected.
53+
Returns:
54+
A JSON document with the key 'success' set to True if the operation
55+
is successful. Otherwise the key 'success' is set to False and the
56+
field 'code' is set to the HTTP error code that represents a specific
57+
reason when the account confirmation was rejected.
5758
58-
Raises:
59-
None
60-
"""
59+
Raises:
60+
None
61+
"""
6162

63+
# noinspection PyMethodMayBeStatic
6264
def post(self):
6365
# Get values
6466
email = request.form.get('email') # User account email address

app/User/services.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ def get_user(id_user):
4343

4444
def get_password_hash(password):
4545
salt = str(uuid.uuid1())
46-
password_hash = hashlib.sha256("%s:%s" % (password, salt)).hexdigest()
46+
password_hash = hashlib.sha256((password + ":" + salt).encode()).hexdigest()
4747
return salt, password_hash
4848

4949

5050
def check_password(id_user, password):
5151
user = get_user(id_user)
52-
password_hash = hashlib.sha256("%s:%s" % (password, user.salt)).hexdigest()
52+
password_hash = hashlib.sha256((password + ":" + user.salt).encode()).hexdigest()
5353
return user.password == password_hash
5454

5555

app/__init__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
# ---------- Constants ----------
5454
CONFIG_FILE = 'cloudsession.ini'
55-
DEFAULT_LOG_PATH = '/var/log/supervisor/cloud-session-app.log'
55+
DEFAULT_LOG_PATH = '/var/log/supervisor/cloud-session-app.log'
5656

5757
# Define the WSGI application object
5858
app = Flask(__name__)
@@ -142,22 +142,22 @@
142142
config['DEFAULT'] = configDefaults
143143

144144
if isfile(configFile):
145+
logging.info('Loading settings from %s.', configFile)
146+
145147
# Load default settings first
146148
# configs = ConfigParser(configDefaults)
147149

148150
# Load configuration file to override default settings
149151
config.read_file(open(configFile))
150-
151152
logging.debug('Configuration Key Settings')
152153

153154
# Load settings from the configuration file into a dictionary
154155
# for section in config.sections():
155-
# logging.debug(('Section: %s', section))
156156
for (key, value) in config.items('application', True):
157-
app_configs[key] = value
158157
logging.debug("Key:%s, Value:%s", key, value)
158+
app_configs[key] = value
159159

160-
# Set the default configuration
160+
logging.info("End of configuration list.")
161161
app.config['CLOUD_SESSION_PROPERTIES'] = app_configs
162162

163163
else:
@@ -225,14 +225,15 @@
225225
if db is not None:
226226
from app.Authenticate.controllers import authenticate_app
227227
from app.AuthToken.controllers import auth_token_app
228+
from app.Health.controllers import health_app
228229
from app.User.controllers import user_app
229230
from app.LocalUser.controllers import local_user_app
230231
from app.RateLimiting.controllers import rate_limiting_app
231232
from app.OAuth.controllers import oauth_app
232233

233-
234234
app.register_blueprint(auth_token_app)
235235
app.register_blueprint(authenticate_app)
236+
app.register_blueprint(health_app)
236237
app.register_blueprint(user_app)
237238
app.register_blueprint(local_user_app)
238239
app.register_blueprint(rate_limiting_app)

app/__version__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@
2727
"""
2828
Change Log
2929
30+
1.3.2 Update supervisor package to accommodate the removal of the cgi
31+
library in python 3.8.
32+
Add API keys for version and ping.
33+
34+
1.3.1 Add error handling to password authentication to trap the possibility
35+
of an unencoded password submission.
36+
Update password hash methods to accommodate a change in default string
37+
handling in Python3.
38+
3039
1.3.0 Update all packages to current releases.
3140
Refactor to support Python 3.7
3241
@@ -46,4 +55,4 @@
4655
4756
"""
4857

49-
__version__ = "1.3.0"
58+
__version__ = "1.3.2"

redis_exercise.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
from redis import Redis
3+
4+
5+
password = "Qb@zGhzfF+jAmphvu?Rvxq9P9Nkjwv3ECCoR+Gc4Qx3FWeN(oUf"
6+
7+
# create a connection to the localhost Redis server instance, by
8+
# default it runs on port 6379
9+
10+
redis_db = Redis(
11+
host="192.168.0.111",
12+
port=6379,
13+
db=0,
14+
password=password)
15+
16+
# see what keys are in Redis
17+
print(redis_db.keys())
18+
19+
# output for keys() should be an empty list "[]"
20+
redis_db.set('full stack', 'python')
21+
22+
# output should be "True"
23+
print(redis_db.keys())
24+
25+
# now we have one key so the output will be "[b'full stack']"
26+
print(redis_db.get('full stack'))
27+
28+
# output is "b'python'", the key and value still exist in Redis
29+
print(redis_db.incr('twilio'))
30+
31+
# output is "1", we just incremented even though the key did not
32+
# previously exist
33+
print(redis_db.get('twilio'))
34+
35+
# output is "b'1'" again, since we just obtained the value from
36+
# the existing key
37+
print(redis_db.delete('twilio'))
38+
39+
# output is "1" because the command was successful
40+
print(redis_db.get('twilio'))
41+
# nothing is returned because the key and value no longer exist

requirements.txt

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,56 @@ itsdangerous==1.1.0
1212
Jinja2==2.10
1313
MarkupSafe==1.1.1
1414
more-itertools==6.0.0
15+
16+
# ===================================================================================
17+
# NOTE:
18+
# There is a bug in the mysqlclient installation process on MocOS systems.
19+
#
20+
# https://pypi.org/project/mysqlclient/
21+
#
22+
# Note about bug of MySQL Connector/C on macOS
23+
#
24+
# See also: https://bugs.mysql.com/bug.php?id=86971
25+
#
26+
# Versions of MySQL Connector/C may have incorrect default configuration
27+
# options that cause compilation errors when mysqlclient-python is installed.
28+
# (As of November 2017, this is known to be true for homebrew's mysql-connector-c
29+
# and official package)
30+
#
31+
# Modification of mysql_config resolves these issues as follows.
32+
#
33+
# Change
34+
#
35+
# on macOS, on or about line 112:
36+
#
37+
# # Create options
38+
# libs="-L$pkglibdir"
39+
# libs="$libs -l "
40+
#
41+
# to
42+
#
43+
# # Create options
44+
# libs="-L$pkglibdir"
45+
# libs="$libs -lmysqlclient -lssl -lcrypto"
46+
#
47+
#
48+
# An improper ssl configuration may also create issues; see, e.g, brew info openssl
49+
# for details on macOS.
50+
# ===================================================================================
51+
1552
mysqlclient==1.4.2.post1
16-
pkg-resources==0.0.0
53+
54+
1755
pluggy==0.9.0
1856
py==1.8.0
1957
pystache==0.5.4
2058
pytz==2018.9
59+
redis==3.2.1
2160
sentry-sdk==0.7.6
2261
six==1.12.0
2362
SQLAlchemy==1.3.0
63+
supervisor==4.2.1
2464
urllib3==1.24.1
25-
uWSGI==2.0.18
65+
uWSGi==2.0.18
2666
validate-email==1.3
2767
Werkzeug==0.14.1

0 commit comments

Comments
 (0)