Skip to content

Commit

Permalink
merged develop into OP-841 and resolved conflicts, replaced visibilit…
Browse files Browse the repository at this point in the history
…y with privacy in confirmation view function, updated confirmation.html page

# Conflicts:
#	app/lib/email_utils.py
#	app/models.py
#	app/request/utils.py
  • Loading branch information
johnyu95 committed Oct 15, 2016
1 parent cba7d8f commit 522ee48
Show file tree
Hide file tree
Showing 48 changed files with 1,205 additions and 641 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ saml/
redis-stable/
python-sudo.sh
quarantine/

.vagrant/
tmp/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
9 changes: 3 additions & 6 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import redis
from business_calendar import Calendar, MO, TU, WE, TH, FR
from celery import Celery
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_kvsession import KVSessionExtension
from flask_login import LoginManager
from flask_mail import Mail
from flask_recaptcha import ReCaptcha
from business_calendar import Calendar, MO, TU, WE, TH, FR
from flask_sqlalchemy import SQLAlchemy
from simplekv.decorator import PrefixDecorator
from simplekv.memory.redisstore import RedisStore
from celery import Celery



from config import config, Config

Expand All @@ -27,7 +24,6 @@
upload_redis = redis.StrictRedis(db=2)

mail = Mail()
app = Flask(__name__)

calendar = Calendar(
workdays=[MO, TU, WE, TH, FR],
Expand Down Expand Up @@ -55,6 +51,8 @@ def create_app(config_name):
:return: Flask application
"""

app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)

Expand All @@ -67,7 +65,6 @@ def create_app(config_name):

with app.app_context():
from app.models import Anonymous

login_manager.login_view = 'auth.login'
login_manager.anonymous_user = Anonymous
KVSessionExtension(prefixed_store, app)
Expand Down
64 changes: 2 additions & 62 deletions app/constants.py → app/constants/__init__.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,5 @@
from app.lib.utils import mapping

ACKNOWLEDGEMENT_DAYS_DUE = 5

ROLE_NAME = mapping(
ANONYMOUS='Anonymous User',
PUBLIC_NON_REQUESTER='Public User - None Requester',
PUBLIC_REQUESTER='Public User - Requester',
AGENCY_HELPER='Agency Helper',
AGENCY_OFFICER='Agency FOIL Officer',
AGENCY_ADMIN='Agency Administrator'
)

# TODO: apply the above mapping convention where appropriate

EVENT_TYPE = {
"user_added": "user_added",
"user_permissions_changed": "user_permissions_changed",
"user_information_edited": "user_information_edited",
"request_created": "request_created",
"request_acknowledged": "request_acknowledged",
"request_status_changed": "request_status_changed",
"request_extended": "request_extended",
"request_closed": "request_closed",
"request_title_edited": "request_title_edited",
"request_agency_description_edited": "request_agency_description_edited",
"request_title_privacy_edited": "request_title_privacy_edited",
"request_agency_description_privacy_edited": "request_agency_description_privacy_edited",
"email_notification_sent": "email_notification_sent",
"file_added": "file_added",
"file_edited": "file_edited",
"file_removed": "file_removed",
"link_added": "link_added",
"link_edited": "link_edited",
"link_removed": "link_removed",
"instructions_added": "instructions_added",
"instructions_edited": "instructions_edited",
"instructions_removed": "instructions_removed",
"note_added": "note_added",
"note_edited": "note_edited",
"note_deleted": "note_deleted",
}

USER_TYPE = {
"anonymous_user": "anonymous_user",
"agency_user": "agency_user",
"public_user": "public_user"
}

CATEGORIES = [
('', ''),
('Business', 'Business'),
Expand Down Expand Up @@ -138,24 +91,11 @@
PUBLIC_USER_MICROSOFT = 'MSLiveSSO'
ANONYMOUS_USER = 'AnonymousUser'

PUBLIC_USER = [
PUBLIC_USER = frozenset((
PUBLIC_USER_NYC_ID,
PUBLIC_USER_FACEBOOK,
PUBLIC_USER_LINKEDIN,
PUBLIC_USER_GOOGLE,
PUBLIC_USER_YAHOO,
PUBLIC_USER_MICROSOFT
]

RESPONSE_TYPE = {
"note": "note",
"record types": "record types",
"file": "file",
"link": "link",
"offline instructions": "offline instructions",
"email": "email",
"sms": "sms",
"push": "push",
"extension": "extension",
"status": "status"
}
))
25 changes: 25 additions & 0 deletions app/constants/event_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
USER_ADDED = "user_added"
USER_PERM_CHANGED = "user_permissions_changed"
USER_INFO_EDITED = "user_information_edited"
REQ_CREATED = "request_created"
REQ_ACKNOWLEDGED = "request_acknowledged"
REQ_STATUS_CHANGED = "request_status_changed"
REQ_EXTENDED = "request_extended"
REQ_CLOSED = "request_closed"
REQ_TITLE_EDITED = "request_title_edited"
REQ_AGENCY_DESC_EDITED = "request_agency_description_edited"
REQ_TITLE_PRIVACY_EDITED = "request_title_privacy_edited"
REQ_AGENCY_DESC_PRIVACY_EDITED = "request_agency_description_privacy_edited"
EMAIL_NOTIFICATION_SENT = "email_notification_sent"
FILE_ADDED = "file_added"
FILE_EDITED = "file_edited"
FILE_REMOVED = "file_removed"
LINK_ADDED = "link_added"
LINK_EDITED = "link_edited"
LINK_REMOVED = "link_removed"
INSTRUCTIONS_ADDED = "instructions_added"
INSTRUCTIONS_EDITED = "instructions_edited"
INSTRUCTIONS_REMOVED = "instructions_removed"
NOTE_ADDED = "note_added"
NOTE_EDITED = "note_edited"
NOTE_DELETED = "note_deleted"
37 changes: 37 additions & 0 deletions app/constants/permission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Duplicate Request (New Request based on same criteria)
DUPLICATE_REQUEST = 0x00001
# View detailed request status (Open, In Progress, Closed)
VIEW_REQUEST_STATUS_PUBLIC = 0x00002
# View detailed request status (Open, In Progress, Due Soon, Overdue, Closed)
VIEW_REQUEST_STATUS_ALL = 0x00004
# View all public request information
VIEW_REQUEST_INFO_PUBLIC = 0x00008
# View all request information
VIEW_REQUEST_INFO_ALL = 0x00010
# Add Note (Agency Only) or (Agency Only & Requester Only) or (Agency Only, Requester / Agency)
ADD_NOTE = 0x00020
# Upload Documents (Agency Only & Requester Only) or (Agency Only / Private) or
# (Agency Only / Private, Agency / Requester, All Users)
UPLOAD_DOCUMENTS = 0x00040
# View Documents Immediately - Public or 'Released and Private'
VIEW_DOCUMENTS_IMMEDIATELY = 0x00080
# View requests where they are assigned
VIEW_REQUESTS_HELPER = 0x00100
# View all requests for their agency
VIEW_REQUESTS_AGENCY = 0x00200
# View all requests for all agencies
VIEW_REQUESTS_ALL = 0x00400
# Extend Request
EXTEND_REQUESTS = 0x00800
# Close Request (Denial/Fulfill)
CLOSE_REQUESTS = 0x01000
# Add Helper (Helper permissions must be specified on a per request basis)
ADD_HELPERS = 0x02000
# Remove Helper
REMOVE_HELPERS = 0x04000
# Acknowledge
ACKNOWLEDGE = 0x08000
# Change Request POC
CHANGE_REQUEST_POC = 0x10000
# All permissions
ADMINISTER = 0x20000
10 changes: 10 additions & 0 deletions app/constants/response_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
NOTE = "note"
RECORD_TYPES = "record types"
FILE = "file"
LINK = "link"
OFFLINE_INSTRUCTIONS = "offline instructions"
EMAIL = "email"
SMS = "sms"
PUSH = "push"
EXTENSION = "extension"
STATUS = "status"
6 changes: 6 additions & 0 deletions app/constants/role_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ANONYMOUS = 'Anonymous User'
PUBLIC_NON_REQUESTER = 'Public User - None Requester'
PUBLIC_REQUESTER = 'Public User - Requester'
AGENCY_HELPER = 'Agency Helper'
AGENCY_OFFICER = 'Agency FOIL Officer'
AGENCY_ADMIN = 'Agency Administrator'
3 changes: 3 additions & 0 deletions app/constants/user_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ANONYMOUS = "anonymous_user"
AGENCY = "agency_user"
PUBLIC = "public_user"
16 changes: 15 additions & 1 deletion app/db_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,27 @@
synopsis: Handles the functions for database control
"""
import json

from contextlib import contextmanager
from app import db

# TODO: Add comment explaining why this is needed
from app.models import Agencies, Users


@contextmanager
def db_session():
"""
Provide a transactional scope around a series of operations.
Flask-SQLAlchemy handles closing the session after an HTTP request.
"""
try:
yield db.session
db.session.commit()
except:
db.session.rollback()
raise


def create_object(obj):
"""
:param obj: Object class being created in database
Expand Down
6 changes: 4 additions & 2 deletions app/lib/email_utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
app.email_utils
~~~~~~~~~~~~~~~~
Implements e-mail notifications for OpenRecords. Flask-mail is a dependency, and the following environment variables
need to be set in order for this to work: (Currently using Fake SMTP for testing)
MAIL_SERVER: 'localhost'
Expand All @@ -12,6 +12,7 @@
MAIL_USERNAME: os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD: os.environ.get('MAIL_PASSWORD')
DEFAULT_MAIL_SENDER: 'Records Admin <openrecords@records.nyc.gov>'
"""

from flask import current_app, render_template
Expand All @@ -28,6 +29,7 @@ def send_email(subject, template, to=list(), cc=list(), bcc=list(), **kwargs):
"""
Function that sends asynchronous emails for the application.
Takes in arguments from the frontend.
:param to: Person(s) email is being sent to
:param cc: Person(s) being CC'ed on the email
:param bcc: Person(s) being BCC'ed on the email
Expand All @@ -43,4 +45,4 @@ def send_email(subject, template, to=list(), cc=list(), bcc=list(), **kwargs):
# Renders email template from .txt file commented out and not currently used in development
# msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.html', **kwargs)
send_async_email.delay(msg)
send_async_email.delay(msg)
30 changes: 30 additions & 0 deletions app/lib/file_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
app.file.utils
~~~~~~~~~~~~~~~~
synopsis: Handles the functions for files
"""
from flask import current_app
import magic
import os


def get_mime_type(request_id, filename):
"""
Gets the mime_type of a file in the uploaded directory using python magic.
:param request_id: Request ID for the specific file.
:param filename: the name of the uploaded file.
:return: mime_type of the file as determined by python magic.
"""

upload_file = os.path.join(current_app.config['UPLOAD_DIRECTORY'], request_id, filename)
mime_type = magic.from_file(upload_file, mime=True)
if current_app.config['MAGIC_FILE'] != '':
# Check using custom mime database file
m = magic.Magic(
magic_file=current_app.config['MAGIC_FILE'],
mime=True)
m.from_file(upload_file)
return mime_type
18 changes: 14 additions & 4 deletions app/lib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
"""


def mapping(**named_values):
return type('Mapping', (), named_values)

from base64 import b64decode

class InvalidUserException(Exception):

Expand All @@ -16,3 +13,16 @@ def __init__(self, user):
"""
super(InvalidUserException, self).__init__(
"Invalid user: {}".format(user))


def b64decode_lenient(data):
"""
Decodes base64 (bytes or str), padding being optional
:param data: a string or bytes-like object of base64 data
:return: a decoded string
"""
if type(data) is str:
data = data.encode()
data += b'=' * (4 - (len(data) % 4))
return b64decode(data).decode()
Loading

0 comments on commit 522ee48

Please sign in to comment.