| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import calendar | 5 import calendar |
| 6 import cgi | 6 import cgi |
| 7 import contextlib | |
| 8 import datetime | 7 import datetime |
| 9 import datetime_encoder | |
| 10 import json | 8 import json |
| 11 import logging | 9 import logging |
| 12 import os | 10 import os |
| 13 import sys | 11 import sys |
| 14 import time | 12 import time |
| 13 import utils |
| 15 import webapp2 | 14 import webapp2 |
| 16 import zlib | 15 import zlib |
| 17 | 16 |
| 18 | 17 |
| 19 from google.appengine.api import app_identity | 18 from google.appengine.api import app_identity |
| 20 from google.appengine.api import memcache | 19 from google.appengine.api import memcache |
| 21 from google.appengine.api import users | 20 from google.appengine.api import users |
| 22 from google.appengine.datastore import datastore_query | |
| 23 from google.appengine.ext import ndb | 21 from google.appengine.ext import ndb |
| 24 | 22 |
| 25 | 23 |
| 26 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | 24 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 27 sys.path.insert(0, os.path.join(BASE_DIR, 'components', 'third_party')) | 25 sys.path.insert(0, os.path.join(BASE_DIR, 'components', 'third_party')) |
| 28 | 26 |
| 29 from components import auth | 27 from components import auth |
| 30 from components import template | 28 from components import template |
| 31 | 29 |
| 32 | 30 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 60 | 58 |
| 61 MSG_TYPE = 'banner-msg' | 59 MSG_TYPE = 'banner-msg' |
| 62 | 60 |
| 63 def set_json_headers(self): | 61 def set_json_headers(self): |
| 64 self.response.headers['Access-Control-Allow-Origin'] = '*' | 62 self.response.headers['Access-Control-Allow-Origin'] = '*' |
| 65 self.response.headers['Content-Type'] = 'application/json' | 63 self.response.headers['Content-Type'] = 'application/json' |
| 66 | 64 |
| 67 def send_json_data(self, data): | 65 def send_json_data(self, data): |
| 68 self.set_json_headers() | 66 self.set_json_headers() |
| 69 self.response.write( | 67 self.response.write( |
| 70 json.dumps(data, cls=datetime_encoder.DateTimeEncoder, indent=1)) | 68 json.dumps(data, cls=utils.DateTimeEncoder, indent=1)) |
| 71 | 69 |
| 72 def get_from_datastore(self, msg_type): | 70 def get_from_datastore(self, msg_type): |
| 73 last_entry = BannerMessage.get_last_datastore(msg_type) | 71 last_entry = BannerMessage.get_last_datastore(msg_type) |
| 74 if last_entry and last_entry.active: | 72 if last_entry and last_entry.active: |
| 75 data = last_entry.to_json_data() | 73 data = last_entry.to_json_data() |
| 76 memcache.set(msg_type, data) | 74 memcache.set(msg_type, data) |
| 77 | 75 |
| 78 self.send_json_data(data) | 76 self.send_json_data(data) |
| 79 return True | 77 return True |
| 80 return False | 78 return False |
| 81 | 79 |
| 82 def get_from_memcache(self, memcache_key): | 80 def get_from_memcache(self, memcache_key): |
| 83 data = memcache.get(memcache_key) | 81 data = memcache.get(memcache_key) |
| 84 if data: | 82 if data: |
| 85 self.send_json_data(data) | 83 self.send_json_data(data) |
| 86 return True | 84 return True |
| 87 return False | 85 return False |
| 88 | 86 |
| 89 def get_msg(self, msg_type): | 87 def get_msg(self, msg_type): |
| 90 if not self.get_from_memcache(msg_type): | 88 if not self.get_from_memcache(msg_type): |
| 91 if not self.get_from_datastore(msg_type): | 89 if not self.get_from_datastore(msg_type): |
| 92 self.send_json_data({}) | 90 self.send_json_data({}) |
| 93 | 91 |
| 94 def get(self): | 92 def get(self): |
| 95 self.get_msg(BannerMessageHandler.MSG_TYPE) | 93 self.get_msg(BannerMessageHandler.MSG_TYPE) |
| 96 | 94 |
| 97 | 95 |
| 98 # TODO(seanmccullough): move this into a general purpose auth lib if | |
| 99 # we need to run this check elsehere in SoM. | |
| 100 def is_trooper_or_admin(): | |
| 101 return (auth.is_group_member("mdb/chrome-troopers") or | |
| 102 users.is_current_user_admin()) | |
| 103 | |
| 104 | |
| 105 class BannerMessageFormHandler(auth.AuthenticatingHandler): | 96 class BannerMessageFormHandler(auth.AuthenticatingHandler): |
| 106 | 97 |
| 107 @auth.autologin | 98 @auth.autologin |
| 108 @auth.require(is_trooper_or_admin) | 99 @auth.require(utils.is_trooper_or_admin) |
| 109 def get(self): | 100 def get(self): |
| 110 user = users.get_current_user() | 101 user = users.get_current_user() |
| 111 template_values = { | 102 template_values = { |
| 112 'user': user, | 103 'user': user, |
| 113 'xsrf_token': self.generate_xsrf_token(), | 104 'xsrf_token': self.generate_xsrf_token(), |
| 114 } | 105 } |
| 115 | 106 |
| 116 latest_msg = BannerMessage.get_last_datastore( | 107 latest_msg = BannerMessage.get_last_datastore( |
| 117 BannerMessageHandler.MSG_TYPE) | 108 BannerMessageHandler.MSG_TYPE) |
| 118 | 109 |
| 119 if latest_msg is not None and latest_msg.active: | 110 if latest_msg is not None and latest_msg.active: |
| 120 template_values['latest_msg'] = latest_msg | 111 template_values['latest_msg'] = latest_msg |
| 121 | 112 |
| 122 self.response.write(template.render('som/banner-msg-form.html', | 113 self.response.write(template.render('som/banner-msg-form.html', |
| 123 template_values)) | 114 template_values)) |
| 124 | 115 |
| 125 def store_msg(self, msg_type, msg): | 116 def store_msg(self, msg_type, msg): |
| 126 uid = int(time.time() * 1000000) | 117 uid = int(time.time() * 1000000) |
| 127 new_entry = BannerMessage( | 118 new_entry = BannerMessage( |
| 128 key=ndb.Key('BannerMessageRoot', '0', BannerMessage, uid), | 119 key=ndb.Key('BannerMessageRoot', '0', BannerMessage, uid), |
| (...skipping 16 matching lines...) Expand all Loading... |
| 145 self.response.set_status(500, 'could not find latest message') | 136 self.response.set_status(500, 'could not find latest message') |
| 146 | 137 |
| 147 def update_msg(self, msg_type): | 138 def update_msg(self, msg_type): |
| 148 if self.request.get('deactivate'): | 139 if self.request.get('deactivate'): |
| 149 return self.deactivate_latest_msg(BannerMessageHandler.MSG_TYPE) | 140 return self.deactivate_latest_msg(BannerMessageHandler.MSG_TYPE) |
| 150 else: | 141 else: |
| 151 content = self.request.get('content') | 142 content = self.request.get('content') |
| 152 if content: | 143 if content: |
| 153 return self.store_msg(msg_type, content) | 144 return self.store_msg(msg_type, content) |
| 154 | 145 |
| 155 @auth.require(is_trooper_or_admin) | 146 @auth.require(utils.is_trooper_or_admin) |
| 156 def post(self): | 147 def post(self): |
| 157 user = users.get_current_user() | 148 user = users.get_current_user() |
| 158 if user: | 149 if user: |
| 159 msg = self.update_msg(BannerMessageHandler.MSG_TYPE) | 150 msg = self.update_msg(BannerMessageHandler.MSG_TYPE) |
| 160 if msg: | 151 if msg: |
| 161 data = msg.to_json_data() | 152 data = msg.to_json_data() |
| 162 memcache.set(BannerMessageHandler.MSG_TYPE, data) | 153 memcache.set(BannerMessageHandler.MSG_TYPE, data) |
| 163 | 154 |
| 164 self.redirect('/banner-msg-form') | 155 self.redirect('/banner-msg-form') |
| 165 else: | 156 else: |
| 166 self.response.set_status(401, 'No user auth') | 157 self.response.set_status(401, 'No user auth') |
| 167 | 158 |
| 168 template.bootstrap({'som': os.path.dirname(__file__)}) | 159 template.bootstrap({'som': os.path.dirname(__file__)}) |
| 169 | 160 |
| 170 app = webapp2.WSGIApplication([ | 161 app = webapp2.WSGIApplication([ |
| 171 ('/banner-msg', BannerMessageHandler), | 162 ('/banner-msg', BannerMessageHandler), |
| 172 ('/banner-msg-form', BannerMessageFormHandler), | 163 ('/banner-msg-form', BannerMessageFormHandler), |
| 173 ]) | 164 ]) |
| OLD | NEW |