<commit_before>import os
import tornado.httpserver
import tornado.ioloop
import tornado.web
from creds import *
from requests import Request
import requests
import json
import re
import tempfile
import redis
import uuid
from pydub import AudioSegment

def gettoken(uid):
	red = redis.from_url(redis_url)
	token = red.get(uid+"-access_token")
	refresh = red.get(uid+"-refresh_token")
	if token:
		return token
	elif refresh:
		payload = {"client_id" : Client_ID, "client_secret" : Client_Secret, "refresh_token" : refresh, "grant_type" : "refresh_token", }
		url = "https://api.amazon.com/auth/o2/token"
		r = requests.post(url, data = payload)
		resp = json.loads(r.text)
		red.set(uid+"-access_token", resp['access_token'])
		red.expire(uid+"-access_token", 3600)
		return resp['access_token']
	else:
		return False

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_cookie("user")

class MainHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def get(self):
		f = open('static/index.html', 'r')
		resp = f.read()
		f.close()
		self.write(resp)
		self.finish()

class StartAuthHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	def get(self):
		scope="alexa_all"
		sd = json.dumps({
		    "alexa:all": {
		        "productID": Product_ID,
		        "productInstanceAttributes": {
		            "deviceSerialNumber": "1"
		        }
		    }
		})
		url = "https://www.amazon.com/ap/oa"
		path = self.request.protocol + "://" + self.request.host
		callback = path + "/code"
		payload = {"client_id" : Client_ID, "scope" : "alexa:all", "scope_data" : sd, "response_type" : "code", "redirect_uri" : callback }
		req = Request('GET', url, params=payload)
		p = req.prepare()
		self.redirect(p.url)

class CodeAuthHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	def get(self):
		code=self.get_argument("code")
		path = self.request.protocol + "://" + self.request.host
		callback = path+"/code"
		payload = {"client_id" : Client_ID, "client_secret" : Client_Secret, "code" : code, "grant_type" : "authorization_code", "redirect_uri" : callback }
		url = "https://api.amazon.com/auth/o2/token"
		r = requests.post(url, data = payload)
		uid = str(uuid.uuid4())
		red = redis.from_url(redis_url)
		resp = json.loads(r.text)
		red.set(uid+"-access_token", resp['access_token'])
		red.expire(uid+"-access_token", 3600)
		red.set(uid+"-refresh_token", resp['refresh_token'])
		self.set_cookie("user", uid)
		self.redirect("/")

class LogoutHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def get(self):
		uid = tornado.escape.xhtml_escape(self.current_user)
		red = redis.from_url(redis_url)
		red.delete(uid+"-access_token")
		red.delete(uid+"-refresh_token")
		self.clear_cookie("user")
		self.set_header('Content-Type', 'text/plain')
		self.write("Logged Out, Goodbye")
		self.finish()

class AudioHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def post(self):
		uid = tornado.escape.xhtml_escape(self.current_user)
		token = gettoken(uid)
		if (token == False):
			self.set_status(403)
		else:
			rxfile = self.request.files['data'][0]['body']
			tf = tempfile.NamedTemporaryFile(suffix=".wav")
			tf.write(rxfile)
			_input = AudioSegment.from_wav(tf.name)
			tf.close()
			tf = tempfile.NamedTemporaryFile(suffix=".wav")
			output = _input.set_channels(1).set_frame_rate(16000)
			f = output.export(tf.name, format="wav")
			url = 'https://access-alexa-na.amazon.com/v1/avs/speechrecognizer/recognize'
			headers = {'Authorization' : 'Bearer %s' % token}
			d = {
		    	"messageHeader": {
		        	"deviceContext": [
		            	{
		                	"name": "playbackState",
		                	"namespace": "AudioPlayer",
		                	"payload": {
		                    	"streamId": "",
		         			   	"offsetInMilliseconds": "0",
		                    	"playerActivity": "IDLE"
		                	}
		            	}
		        	]
		    	},
		    	"messageBody": {
		        	"profile": "alexa-close-talk",
		        	"locale": "en-us",
		        	"format": "audio/L16; rate=16000; channels=1"
		    	}
			}
			files = [
				('file', ('request', json.dumps(d), 'application/json; charset=UTF-8')),
				('file', ('audio', tf, 'audio/L16; rate=16000; channels=1'))
			]
			r = requests.post(url, headers=headers, files=files)
			tf.close()
			for v in r.headers['content-type'].split(";"):
				if re.match('.*boundary.*', v):
					boundary =  v.split("=")[1]
			data = r.content.split(boundary)
			for d in data:
				if (len(d) >= 1024):
			 	   audio = d.split('\r\n\r\n')[1].rstrip('--')
			self.set_header('Content-Type', 'audio/mpeg')
			self.write(audio)
		self.finish()

def main():
	settings = {
	    "cookie_secret": "parisPOLANDbroadFENCEcornWOULD",
	    "login_url": "/static/welcome.html",
	}
	static_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
	application = tornado.web.Application([(r"/", MainHandler),
											(r"/start", StartAuthHandler),
											(r"/code", CodeAuthHandler),
											(r"/logout", LogoutHandler),
											(r"/audio", AudioHandler),
											(r'/(favicon.ico)', tornado.web.StaticFileHandler,{'path': static_path}),
											(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': static_path}),
											], **settings)
	http_server = tornado.httpserver.HTTPServer(application)
	port = int(os.environ.get("PORT", 8080))
	http_server.listen(port)
	tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
	main()

<commit_msg>add text route for alexaweb<commit_after>import os
import tornado.httpserver
import tornado.ioloop
import tornado.web
from creds import *
from requests import Request
import requests
import json
import re
import tempfile
import redis
import uuid
import random
import string
from pydub import AudioSegment

def gettoken(uid):
	red = redis.from_url(redis_url)
	token = red.get(uid+"-access_token")
	refresh = red.get(uid+"-refresh_token")
	if token:
		return token
	elif refresh:
		payload = {"client_id" : Client_ID, "client_secret" : Client_Secret, "refresh_token" : refresh, "grant_type" : "refresh_token", }
		url = "https://api.amazon.com/auth/o2/token"
		r = requests.post(url, data = payload)
		resp = json.loads(r.text)
		red.set(uid+"-access_token", resp['access_token'])
		red.expire(uid+"-access_token", 3600)
		return resp['access_token']
	else:
		return False

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_cookie("user")

class MainHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def get(self):
		f = open('static/index.html', 'r')
		resp = f.read()
		f.close()
		self.write(resp)
		self.finish()

class StartAuthHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	def get(self):
		scope="alexa_all"
		sd = json.dumps({
		    "alexa:all": {
		        "productID": Product_ID,
		        "productInstanceAttributes": {
		            "deviceSerialNumber": "1"
		        }
		    }
		})
		url = "https://www.amazon.com/ap/oa"
		path = self.request.protocol + "://" + self.request.host
		callback = path + "/code"
		payload = {"client_id" : Client_ID, "scope" : "alexa:all", "scope_data" : sd, "response_type" : "code", "redirect_uri" : callback }
		req = Request('GET', url, params=payload)
		p = req.prepare()
		self.redirect(p.url)

class CodeAuthHandler(tornado.web.RequestHandler):
	@tornado.web.asynchronous
	def get(self):
		code=self.get_argument("code")
		path = self.request.protocol + "://" + self.request.host
		callback = path+"/code"
		payload = {"client_id" : Client_ID, "client_secret" : Client_Secret, "code" : code, "grant_type" : "authorization_code", "redirect_uri" : callback }
		url = "https://api.amazon.com/auth/o2/token"
		r = requests.post(url, data = payload)
		uid = str(uuid.uuid4())
		red = redis.from_url(redis_url)
		resp = json.loads(r.text)
		red.set(uid+"-access_token", resp['access_token'])
		red.expire(uid+"-access_token", 3600)
		red.set(uid+"-refresh_token", resp['refresh_token'])
		self.set_cookie("user", uid)
		self.redirect("/")

class LogoutHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def get(self):
		uid = tornado.escape.xhtml_escape(self.current_user)
		red = redis.from_url(redis_url)
		red.delete(uid+"-access_token")
		red.delete(uid+"-refresh_token")
		self.clear_cookie("user")
		self.set_header('Content-Type', 'text/plain')
		self.write("Logged Out, Goodbye")
		self.finish()

class AudioHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def post(self):
		uid = tornado.escape.xhtml_escape(self.current_user)
		token = gettoken(uid)
		if (token == False):
			self.set_status(403)
		else:
			rxfile = self.request.files['data'][0]['body']
			tf = tempfile.NamedTemporaryFile(suffix=".wav")
			tf.write(rxfile)
			_input = AudioSegment.from_wav(tf.name)
			tf.close()
			tf = tempfile.NamedTemporaryFile(suffix=".wav")
			output = _input.set_channels(1).set_frame_rate(16000)
			f = output.export(tf.name, format="wav")
			url = 'https://access-alexa-na.amazon.com/v1/avs/speechrecognizer/recognize'
			headers = {'Authorization' : 'Bearer %s' % token}
			d = {
		    	"messageHeader": {
		        	"deviceContext": [
		            	{
		                	"name": "playbackState",
		                	"namespace": "AudioPlayer",
		                	"payload": {
		                    	"streamId": "",
		         			   	"offsetInMilliseconds": "0",
		                    	"playerActivity": "IDLE"
		                	}
		            	}
		        	]
		    	},
		    	"messageBody": {
		        	"profile": "alexa-close-talk",
		        	"locale": "en-us",
		        	"format": "audio/L16; rate=16000; channels=1"
		    	}
			}
			files = [
				('file', ('request', json.dumps(d), 'application/json; charset=UTF-8')),
				('file', ('audio', tf, 'audio/L16; rate=16000; channels=1'))
			]
			r = requests.post(url, headers=headers, files=files)
			tf.close()
			for v in r.headers['content-type'].split(";"):
				if re.match('.*boundary.*', v):
					boundary =  v.split("=")[1]
			data = r.content.split(boundary)
			for d in data:
				if (len(d) >= 1024):
			 	   audio = d.split('\r\n\r\n')[1].rstrip('--')
			self.set_header('Content-Type', 'audio/mpeg')
			self.write(audio)
		self.finish()

class TextHandler(BaseHandler):
	@tornado.web.authenticated
	@tornado.web.asynchronous
	def get(self):
		text = self.get_argument("text", None, True)

		uid = tornado.escape.xhtml_escape(self.current_user)
		token = gettoken(uid)
		if (token == False):
			self.set_status(403)
		else:
			# rxfile = self.request.files['data'][0]['body']
			# tf = tempfile.NamedTemporaryFile(suffix=".wav")
			# tf.write(rxfile)
			# _input = AudioSegment.from_wav(tf.name)
			# tf.close()
			# tf = tempfile.NamedTemporaryFile(suffix=".wav")
			# output = _input.set_channels(1).set_frame_rate(16000)
			# f = output.export(tf.name, format="wav")

			random_str = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(20))
			file_name = "/tmp/{}.wav".format(random_str)

			os.system('os.system("espeak "hello" --stdout > {}")'.format(file_name))

			url = 'https://access-alexa-na.amazon.com/v1/avs/speechrecognizer/recognize'
			headers = {'Authorization' : 'Bearer %s' % token}
			d = {
		    	"messageHeader": {
		        	"deviceContext": [
		            	{
		                	"name": "playbackState",
		                	"namespace": "AudioPlayer",
		                	"payload": {
		                    	"streamId": "",
		         			   	"offsetInMilliseconds": "0",
		                    	"playerActivity": "IDLE"
		                	}
		            	}
		        	]
		    	},
		    	"messageBody": {
		        	"profile": "alexa-close-talk",
		        	"locale": "en-us",
		        	"format": "audio/L16; rate=16000; channels=1"
		    	}
			}
			files = [
				('file', ('request', json.dumps(d), 'application/json; charset=UTF-8')),
				('file', ('audio', open(file_name), 'audio/L16; rate=16000; channels=1'))
			]
			r = requests.post(url, headers=headers, files=files)
			tf.close()
			for v in r.headers['content-type'].split(";"):
				if re.match('.*boundary.*', v):
					boundary =  v.split("=")[1]
			data = r.content.split(boundary)
			for d in data:
				if (len(d) >= 1024):
			 	   audio = d.split('\r\n\r\n')[1].rstrip('--')
			self.set_header('Content-Type', 'audio/mpeg')
			self.write(audio)
		self.finish()

def main():
	settings = {
	    "cookie_secret": "parisPOLANDbroadFENCEcornWOULD",
	    "login_url": "/static/welcome.html",
	}
	static_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static')
	application = tornado.web.Application([(r"/", MainHandler),
											(r"/start", StartAuthHandler),
											(r"/code", CodeAuthHandler),
											(r"/logout", LogoutHandler),
											(r"/audio", AudioHandler),
											(r"/text", TextHandler),
											(r'/(favicon.ico)', tornado.web.StaticFileHandler,{'path': static_path}),
											(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': static_path}),
											], **settings)
	http_server = tornado.httpserver.HTTPServer(application)
	port = int(os.environ.get("PORT", 8080))
	http_server.listen(port)
	tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
	main()

<|endoftext|>


<commit_before>from lib.IntervalTree import IntervalTree
import sys

def addInterval(dic, key, s1, s2):
	interval = [int(s1), int(s2)]
	start = min(interval)
	end = max(interval)
	if key in dic:
		dic[key].append((start, end))
	else:
		dic[key] = [(start,end)]

def parseGFF(file_name):
	ret = {}
	with open(file_name, "rb") as gff:
		for entry in gff:
			split = entry.split()
			addInterval(ret, split[0], split[3], split[4])
	return (ret)

def parseBED(file_name):
	ret = {}
	with open(file_name, "rb") as bed:
		for entry in bed:
			split = entry.split()
			addInterval(ret, split[0], split[1], split[2])
	return (ret)

def parseFile(file_name):
	if (file_name[-4:] == ".gff"):
		return (parseGFF(file_name))
	elif(file_name[-4:] == ".bed"):
		return (parseBED(file_name))
	else:
		raise ValueError("Must take either GFF file or BED file")

def main(argc, argv):
	if (argc != 3):
		print("Takes two files of either GFF or BED format")
		return (-1)
	base = parseFile(argv[1])
	search = parseFile(argv[2])
	for chrom in base:
		base[chrom].sort()
		baseTree = IntervalTree(base[chrom])
		print("Chromosome:{}".format(chrom))
		if chrom in search:
			search[chrom].sort(key=lambda x: (x[0], x[1]))
			for interval in search[chrom]:
				overlap = baseTree.querey(interval)
				print("\tQuerey:{}\n\tOverlaps {}\n".format(interval, overlap))

main(len(sys.argv), sys.argv)
<commit_msg>Remove redunant lambda from sort<commit_after>from lib.IntervalTree import IntervalTree
import sys

def addInterval(dic, key, s1, s2):
	interval = [int(s1), int(s2)]
	start = min(interval)
	end = max(interval)
	if key in dic:
		dic[key].append((start, end))
	else:
		dic[key] = [(start,end)]

def parseGFF(file_name):
	ret = {}
	with open(file_name, "rb") as gff:
		for entry in gff:
			split = entry.split()
			addInterval(ret, split[0], split[3], split[4])
	return (ret)

def parseBED(file_name):
	ret = {}
	with open(file_name, "rb") as bed:
		for entry in bed:
			split = entry.split()
			addInterval(ret, split[0], split[1], split[2])
	return (ret)

def parseFile(file_name):
	if (file_name[-4:] == ".gff"):
		return (parseGFF(file_name))
	elif(file_name[-4:] == ".bed"):
		return (parseBED(file_name))
	else:
		raise ValueError("Must take either GFF file or BED file")

def main(argc, argv):
	if (argc != 3):
		print("Takes two files of either GFF or BED format")
		return (-1)
	base = parseFile(argv[1])
	search = parseFile(argv[2])
	for chrom in base:
		base[chrom].sort()
		baseTree = IntervalTree(base[chrom])
		print("Chromosome:{}".format(chrom))
		if chrom in search:
			search[chrom].sort()
			for interval in search[chrom]:
				overlap = baseTree.querey(interval)
				print("\tQuerey:{}\n\tOverlaps {}\n".format(interval, overlap))

main(len(sys.argv), sys.argv)
<|endoftext|>


<commit_before># Copyright (C) 2014 Linaro Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""The RequestHandler for /token URLs."""

import tornado

from functools import partial
from tornado.web import (
    asynchronous,
)
from urlparse import urlunparse

from handlers.base import BaseHandler
from handlers.common import (
    TOKEN_VALID_KEYS,
    get_query_fields,
)
from handlers.decorators import protected_th
from handlers.response import HandlerResponse
from models import (
    ADMIN_KEY,
    DELETE_KEY,
    EMAIL_KEY,
    EXPIRES_KEY,
    GET_KEY,
    IP_ADDRESS_KEY,
    IP_RESTRICTED,
    POST_KEY,
    SUPERUSER_KEY,
    TOKEN_COLLECTION,
    TOKEN_KEY,
    USERNAME_KEY,
)
from models.token import Token
from utils.db import (
    delete,
    find_one,
    save,
    update,
)

class TokenHandler(BaseHandler):
    """Handle the /token URLs."""

    def __init__(self, application, request, **kwargs):
        super(TokenHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[TOKEN_COLLECTION]

    @staticmethod
    def _valid_keys(method):
        return TOKEN_VALID_KEYS.get(method, None)

    @protected_th("GET")
    @asynchronous
    def get(self, *args, **kwargs):
        self.executor.submit(
            partial(self.execute_get, *args, **kwargs)
        ).add_done_callback(
            lambda future:
            tornado.ioloop.IOLoop.instance().add_callback(
                partial(self._create_valid_response, future.result())
            )
        )

    def _get_one(self, doc_id):
        # Overridden: with the token we do not search by _id, but
        # by token field.
        response = HandlerResponse()
        response.result = None

        result = find_one(
            self.collection,
            doc_id,
            field=TOKEN_KEY,
            fields=get_query_fields(self.get_query_arguments)
        )

        if result:
            response.result = [result]
        else:
            response.status_code = 404
            response.reason = "Resource '%s' not found" % doc_id

        return response

    @protected_th("POST")
    @asynchronous
    def post(self, *args, **kwargs):
        self.executor.submit(
            partial(self.execute_post, *args, **kwargs)
        ).add_done_callback(
            lambda future: tornado.ioloop.IOLoop.instance().add_callback(
                partial(self._create_valid_response, future.result())
            )
        )

    def _post(self, *args, **kwargs):
        response = None

        if kwargs and kwargs.get('id', None):
            self.log.info(
                "Token update from IP address %s",
                self.request.remote_ip
            )
            response = self._update_data(kwargs['id'], kwargs['json_obj'])
        else:
            self.log.info(
                "New token creation from IP address %s",
                self.request.remote_ip
            )
            response = self._new_data(kwargs['json_obj'])

        return response

    def _new_data(self, json_obj):
        """Create a new token in the DB.

        :param json_obj: The JSON object with the paramters.
        :return A `HandlerResponse` object.
        """
        response = HandlerResponse(201)
        response.result = None

        try:
            new_token = self._token_update_create(json_obj)

            response.status_code = save(self.db, new_token)
            if response.status_code == 201:
                response.result = {TOKEN_KEY: new_token.token}
                location = urlunparse(
                    (
                        'http',
                        self.request.headers.get('Host'),
                        self.request.uri + '/' + new_token.token,
                        '', '', ''
                    )
                )
                response.headers = {'Location': location}
        except KeyError:
            response.status_code = 400
            response.reason = (
                "New tokens require the email address field [email]"
            )
        except (TypeError, ValueError):
            response.status_code = 400
            response.reason = "Wrong field value or type in the JSON data"
        except Exception, ex:
            response.status_code = 400
            response.reason = str(ex)

        return response

    def _update_data(self, doc_id, json_obj):
        """Update an existing `Token` in the DB.

        :param doc_id: The token string identifying the `Token` to update.
        :param json_obj: The JSON object with the parameters.
        :return A `HandlerResponse` objet.
        """
        response = HandlerResponse()
        response.result = None

        result = find_one(self.collection, doc_id, field=TOKEN_KEY)

        if result:
            token = Token.from_json(result)

            try:
                token = self._token_update_create(json_obj, token, fail=False)
                response.status_code = update(
                    self.collection, {'token': doc_id}, token.to_dict()
                )
                if response.status_code == 200:
                    response.result = {TOKEN_KEY: token.token}
            except KeyError:
                response.status_code = 400
                response.reason = (
                    "Mandatory field missing"
                )
            except (TypeError, ValueError):
                response.status_code = 400
                response.reason = "Wrong field value or type in the JSON data"
            except Exception, ex:
                response.status_code = 400
                response.reason = str(ex)
        else:
            response.status_code = 404

        return response

    @staticmethod
    def _token_update_create(json_obj, token=None, fail=True):
        """Create or update a `Token` object.

        If the `token` argument is null, a new one will be created.

        :param json_obj: The JSON object with the values to update.
        :param token: The `Token` to update. Default to None meaning a new
            token will be created.
        param fail: If when a mandatory Token field is missing we should fail.
            By default True, and it fails when the `email` field is missing.
        :return A `Token`.
        :raise KeyError, ValueError, TypeError, Exception.
        """
        if not token:
            token = Token()

        if fail:
            token.email = json_obj[EMAIL_KEY]
        else:
            if json_obj.get(EMAIL_KEY, None):
                token.email = json_obj.get(EMAIL_KEY)

        if json_obj.get(USERNAME_KEY, None):
            token.username = json_obj.get(USERNAME_KEY)

        if json_obj.get(EXPIRES_KEY, None):
            token.expires_on = json_obj.get(EXPIRES_KEY)

        if json_obj.get(GET_KEY, None):
            token.is_get_token = json_obj.get(GET_KEY)

        if json_obj.get(POST_KEY, None):
            token.is_post_token = json_obj.get(POST_KEY)

        if json_obj.get(DELETE_KEY, None):
            token.is_delete_token = json_obj.get(DELETE_KEY)

        if json_obj.get(SUPERUSER_KEY, None):
            token.is_superuser = json_obj.get(SUPERUSER_KEY)

        if json_obj.get(ADMIN_KEY, None):
            token.is_admin = json_obj.get(ADMIN_KEY)

        if json_obj.get(IP_RESTRICTED, None):
            token.is_ip_restricted = json_obj.get(IP_RESTRICTED)

        if token.is_ip_restricted and not json_obj.get(IP_ADDRESS_KEY, None):
            raise Exception("IP restricted but no IP addresses given")
        elif json_obj.get(IP_ADDRESS_KEY, None) and not token.is_ip_restricted:
            raise Exception(
                "IP addresses given, but token is not IP restricted"
            )
        elif token.is_ip_restricted and json_obj.get(IP_ADDRESS_KEY, None):
            token.ip_address = json_obj.get(IP_ADDRESS_KEY)

        return token

    @protected_th("DELETE")
    @asynchronous
    def delete(self, *args, **kwargs):
        self.executor.submit(
            partial(self.execute_delete, *args, **kwargs)
        ).add_done_callback(
            lambda future:
            tornado.ioloop.IOLoop.instance().add_callback(
                partial(self._create_valid_response, future.result()))
        )

    def execute_delete(self, *args, **kwargs):
        """Called by the actual DELETE method.

        Make sure we have the correct value to execute a DELETE on the db,
        and then call the method that does the real delete.

        Subclasses should not override this unless there are special reasons
        to.
        """
        response = HandlerResponse(400)

        if kwargs and kwargs.get('id', None):
            response.status_code = self._delete(kwargs['id'])
            if response.status_code == 200:
                response.reason = "Resource deleted"

        return response

    def _delete(self, doc_id):
        ret_val = 404

        self.log.info("Tolen deletion by IP %s", self.request.remote_ip)
        if find_one(self.collection, doc_id, field=TOKEN_KEY):
            ret_val = delete(self.collection, {TOKEN_KEY: {'$in': [doc_id]}})

        return ret_val
<commit_msg>token: Refactor token validation decorator.<commit_after># Copyright (C) 2014 Linaro Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""The RequestHandler for /token URLs."""

from urlparse import urlunparse

from handlers.base import BaseHandler
from handlers.common import (
    NOT_VALID_TOKEN,
    TOKEN_VALID_KEYS,
    get_query_fields,
    valid_token_th,
)
from handlers.response import HandlerResponse
from models import (
    ADMIN_KEY,
    DELETE_KEY,
    EMAIL_KEY,
    EXPIRES_KEY,
    GET_KEY,
    IP_ADDRESS_KEY,
    IP_RESTRICTED,
    POST_KEY,
    SUPERUSER_KEY,
    TOKEN_COLLECTION,
    TOKEN_KEY,
    USERNAME_KEY,
)
from models.token import Token
from utils.db import (
    delete,
    find_one,
    save,
    update,
)

class TokenHandler(BaseHandler):
    """Handle the /token URLs."""

    def __init__(self, application, request, **kwargs):
        super(TokenHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[TOKEN_COLLECTION]

    @staticmethod
    def _valid_keys(method):
        return TOKEN_VALID_KEYS.get(method, None)

    @staticmethod
    def _token_validation_func():
        return valid_token_th

    def _get_one(self, doc_id):
        # Overridden: with the token we do not search by _id, but
        # by token field.
        response = HandlerResponse()
        response.result = None

        result = find_one(
            self.collection,
            doc_id,
            field=TOKEN_KEY,
            fields=get_query_fields(self.get_query_arguments)
        )

        if result:
            response.result = [result]
        else:
            response.status_code = 404
            response.reason = "Resource '%s' not found" % doc_id

        return response

    def _post(self, *args, **kwargs):
        response = None

        if kwargs and kwargs.get('id', None):
            self.log.info(
                "Token update from IP address %s",
                self.request.remote_ip
            )
            response = self._update_data(kwargs['id'], kwargs['json_obj'])
        else:
            self.log.info(
                "New token creation from IP address %s",
                self.request.remote_ip
            )
            response = self._new_data(kwargs['json_obj'])

        return response

    def _new_data(self, json_obj):
        """Create a new token in the DB.

        :param json_obj: The JSON object with the paramters.
        :return A `HandlerResponse` object.
        """
        response = HandlerResponse(201)
        response.result = None

        try:
            new_token = self._token_update_create(json_obj)

            response.status_code = save(self.db, new_token)
            if response.status_code == 201:
                response.result = {TOKEN_KEY: new_token.token}
                location = urlunparse(
                    (
                        'http',
                        self.request.headers.get('Host'),
                        self.request.uri + '/' + new_token.token,
                        '', '', ''
                    )
                )
                response.headers = {'Location': location}
        except KeyError:
            response.status_code = 400
            response.reason = (
                "New tokens require the email address field [email]"
            )
        except (TypeError, ValueError):
            response.status_code = 400
            response.reason = "Wrong field value or type in the JSON data"
        except Exception, ex:
            response.status_code = 400
            response.reason = str(ex)

        return response

    def _update_data(self, doc_id, json_obj):
        """Update an existing `Token` in the DB.

        :param doc_id: The token string identifying the `Token` to update.
        :param json_obj: The JSON object with the parameters.
        :return A `HandlerResponse` objet.
        """
        response = HandlerResponse()
        response.result = None

        result = find_one(self.collection, doc_id, field=TOKEN_KEY)

        if result:
            token = Token.from_json(result)

            try:
                token = self._token_update_create(json_obj, token, fail=False)
                response.status_code = update(
                    self.collection, {'token': doc_id}, token.to_dict()
                )
                if response.status_code == 200:
                    response.result = {TOKEN_KEY: token.token}
            except KeyError:
                response.status_code = 400
                response.reason = (
                    "Mandatory field missing"
                )
            except (TypeError, ValueError):
                response.status_code = 400
                response.reason = "Wrong field value or type in the JSON data"
            except Exception, ex:
                response.status_code = 400
                response.reason = str(ex)
        else:
            response.status_code = 404

        return response

    @staticmethod
    def _token_update_create(json_obj, token=None, fail=True):
        """Create or update a `Token` object.

        If the `token` argument is null, a new one will be created.

        :param json_obj: The JSON object with the values to update.
        :param token: The `Token` to update. Default to None meaning a new
            token will be created.
        param fail: If when a mandatory Token field is missing we should fail.
            By default True, and it fails when the `email` field is missing.
        :return A `Token`.
        :raise KeyError, ValueError, TypeError, Exception.
        """
        if not token:
            token = Token()

        if fail:
            token.email = json_obj[EMAIL_KEY]
        else:
            if json_obj.get(EMAIL_KEY, None):
                token.email = json_obj.get(EMAIL_KEY)

        if json_obj.get(USERNAME_KEY, None):
            token.username = json_obj.get(USERNAME_KEY)

        if json_obj.get(EXPIRES_KEY, None):
            token.expires_on = json_obj.get(EXPIRES_KEY)

        if json_obj.get(GET_KEY, None):
            token.is_get_token = json_obj.get(GET_KEY)

        if json_obj.get(POST_KEY, None):
            token.is_post_token = json_obj.get(POST_KEY)

        if json_obj.get(DELETE_KEY, None):
            token.is_delete_token = json_obj.get(DELETE_KEY)

        if json_obj.get(SUPERUSER_KEY, None):
            token.is_superuser = json_obj.get(SUPERUSER_KEY)

        if json_obj.get(ADMIN_KEY, None):
            token.is_admin = json_obj.get(ADMIN_KEY)

        if json_obj.get(IP_RESTRICTED, None):
            token.is_ip_restricted = json_obj.get(IP_RESTRICTED)

        if token.is_ip_restricted and not json_obj.get(IP_ADDRESS_KEY, None):
            raise Exception("IP restricted but no IP addresses given")
        elif json_obj.get(IP_ADDRESS_KEY, None) and not token.is_ip_restricted:
            raise Exception(
                "IP addresses given, but token is not IP restricted"
            )
        elif token.is_ip_restricted and json_obj.get(IP_ADDRESS_KEY, None):
            token.ip_address = json_obj.get(IP_ADDRESS_KEY)

        return token

    def execute_delete(self, *args, **kwargs):
        """Called by the actual DELETE method.

        Make sure we have the correct value to execute a DELETE on the db,
        and then call the method that does the real delete.

        Subclasses should not override this unless there are special reasons
        to.
        """
        response = HandlerResponse(400)

        if self._validate_req_token("DELETE"):
            if kwargs and kwargs.get('id', None):
                response.status_code = self._delete(kwargs['id'])
                if response.status_code == 200:
                    response.reason = "Resource deleted"
        else:
            response.status_code = 403
            response.reason = NOT_VALID_TOKEN

        return response

    def _delete(self, doc_id):
        ret_val = 404

        self.log.info("Tolen deletion by IP %s", self.request.remote_ip)
        if find_one(self.collection, doc_id, field=TOKEN_KEY):
            ret_val = delete(self.collection, {TOKEN_KEY: {'$in': [doc_id]}})

        return ret_val
<|endoftext|>


<commit_before># Copyright 2014 Dave Kludt
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from flask import (
    g, render_template, request, redirect, url_for, flash, jsonify, session,
    make_response
)
from flask.ext.cloudadmin.decorators import check_perms
from flask.ext.classy import FlaskView, route
from flask.ext.restful import Resource
from bson.objectid import ObjectId
from models import Region

import forms
import tasks
import helper

class BaseView(FlaskView):
    route_base = '/'

    def index(self):
        return render_template('index.html')

class LookupView(FlaskView):
    route_base = '/lookup'
    decorators = [check_perms(request)]

    def index(self):
        form = forms.DCSelect()
        form.data_center.choices = helper.gather_dc_choices()
        return render_template('lookup.html', form=form)

    @route('/servers', methods=['POST'])
    @route('/servers/<task_id>')
    def gather_servers(self, task_id=None):
        if request.method == 'POST':
            task = tasks.generate_account_server_list.delay(
                session.get('ddi'),
                session.get('token'),
                request.json.get('data_center'),
                request.json.get('lookup_type'),
                True
            )
            return jsonify(task_id=task.task_id)
        else:
            status = tasks.check_task_state(task_id)
            if status == 'PENDING':
                return jsonify(state=status, code=204)
            elif status == 'SUCCESS':
                account_id = tasks.get_task_results(task_id)
                account_data = g.db.accounts.find_one(
                    {'_id': ObjectId(account_id)}
                )
                mismatch = False
                if (
                    account_data.get('lookup_type') == 'host_server' and
                    len(account_data.get('servers')) !=
                    len(account_data.get('host_servers'))
                ):
                    mismatch = True

                return render_template(
                    '_server_breakdown.html',
                    data=account_data,
                    mismatch=mismatch,
                    task_id=task_id
                )

            return jsonify(state=status, code=500)

    @route('/servers/<task_id>/csv')
    def generate_server_csv(self, task_id):
        status = tasks.check_task_state(task_id)
        if status == 'SUCCESS':
            account_id = tasks.get_task_results(task_id)
            account_data = g.db.accounts.find_one(
                {'_id': ObjectId(account_id)}
            )
            template = render_template(
                'servers.csv',
                data=account_data
            )
            response = make_response(template)
            response.headers['Content-Type'] = 'application/csv'
            response.headers['Content-Disposition'] = (
                'attachment; filename="servers.csv"'
            )
            return response
        else:
            flash(
                'Task has not completed yet, so no CSV can be generated',
                'warning'
            )
            return redirect(url_for('BaseView:index'))

class ManagementView(FlaskView):
    route_base = '/manage'
    decorators = [check_perms(request)]

    @route('/regions', methods=['GET', 'POST'])
    def define_available_regions(self):
        settings = g.db.settings.find_one()
        form = forms.RegionSet()
        if request.method == 'POST' and form.validate_on_submit():
            region = Region(request.form)
            if region:
                action, data = '$push', region.__dict__
                if not settings.get('regions'):
                    action, data = '$set', [data]

                g.db.settings.update(
                    {
                        '_id': settings.get('_id')
                    }, {
                        action: {
                            'regions': data
                        }
                    }
                )
                flash('Region successfully added to system', 'success')
                return redirect(
                    url_for(
                        'ManagementView:define_available_regions'
                    )
                )
        else:
            if request.method == 'POST':
                flash(
                    'There was a form validation error, please '
                    'check the required values and try again.',
                    'error'
                )

        return render_template(
            'manage/manage_regions.html',
            form=form,
            settings=settings
        )

    @route('/<key>/<action>/<value>')
    def managed_data_actions(self, key, action, value):
        actions = ['activate', 'deactivate', 'remove']
        maps = {
            'regions': {
                'search': 'regions.abbreviation',
                'status': 'regions.$.active',
                'redirect': '/manage/regions',
                'flash_title': value.upper()
            }
        }
        if maps.get(key):
            options = maps.get(key)
            if action in actions:
                found = g.db.settings.find_one(
                    {
                        options.get('search'): value
                    }
                )
                if found:
                    if action == 'remove':
                        keys = options.get('search').split('.')
                        change = {'$pull': {keys[0]: {keys[1]: value}}}
                    else:
                        if action == 'activate':
                            change = {'$set': {options.get('status'): True}}
                        elif action == 'deactivate':
                            change = {'$set': {options.get('status'): False}}

                    g.db.settings.update(
                        {options.get('search'): value},
                        change
                    )
                    flash(
                        '%s was %sd successfully' % (
                            options.get('flash_title'),
                            action
                        ),
                        'success'
                    )
                else:
                    flash(
                        '%s was not found so no action taken' % value.title(),
                        'error'
                    )
            else:
                flash('Invalid action given so no action taken', 'error')
            return redirect(options.get('redirect'))
        else:
            flash('Invalid data key given so no action taken', 'error')
            return redirect('/')

""" API Classes """

class TaskAPI(Resource):
    def get(self, task_id):
        return jsonify(task_status=tasks.check_task_state(task_id))

class AccountAPI(Resource):
    def get(self, account_id, region):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        account_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'cache_expiration': {
                    '$gte': helper.get_timestamp()
                }
            }, {
                '_id': 0,
                'servers': 1
            }
        )
        return jsonify(data=account_data)

    def post(self, account_id, region):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        task_id = tasks.generate_account_server_list.delay(
            account_id,
            token,
            region,
            'host_server'
        )
        return jsonify(task_id=str(task_id))

    def delete(self, account_id, region):
        try:
            g.db.accounts.remove(
                {
                    'account_number': account_id,
                    'region': region
                }
            )
            return 'Request was successful', 204
        except:
            return helper.generate_error(
                'An error occured that prevented the delete to complete',
                500
            )

class ServerAPI(Resource):
    def put(self, account_id, region, server_id):
        """
            Update the account data with the new server, and return True
            or False as to whether the server is by itself on the hypervisor
            Save the data into cache as either way it will still reside on a
            host that has another server or by itself. The answer will be
            correct either way
        """
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        account_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'cache_expiration': {'$gte': helper.get_timestamp()}
            }
        )
        if not account_data:
            return helper.generate_error(
                'You must initialize before checking a server',
                400
            )

        check_server = g.db.accounts.find_one({'servers.id': server_id})
        if check_server:
            return helper.generate_error(
                'Server has been catalogued already',
                400
            )

        response = tasks.check_add_server_to_cache(
            token,
            region,
            account_id,
            server_id,
            account_data
        )
        return jsonify(duplicate=response)

    def get(self, account_id, region, server_id):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        server_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'servers.id': server_id
            }, {
                'servers.$': 1
            }
        )
        if not server_data:
            return helper.generate_error(
                'Server was not found',
                404
            )

        check_host = server_data.get('servers')[0].get('host_id')
        host_servers = helper.generate_servers_on_same_host(
            account_id,
            region,
            check_host
        )
        duplicate = False
        if host_servers is not None and len(host_servers) > 1:
            duplicate = True

        return jsonify(duplicate=duplicate, host_servers=host_servers)
<commit_msg>Put redirect in to go to lookup after login<commit_after># Copyright 2014 Dave Kludt
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from flask import (
    g, render_template, request, redirect, url_for, flash, jsonify, session,
    make_response
)
from flask.ext.cloudadmin.decorators import check_perms
from flask.ext.classy import FlaskView, route
from flask.ext.restful import Resource
from bson.objectid import ObjectId
from models import Region

import forms
import tasks
import helper

class BaseView(FlaskView):
    route_base = '/'

    def index(self):
        if session and session.get('token'):
            return redirect('/lookup/')

        return render_template('index.html')

class LookupView(FlaskView):
    route_base = '/lookup'
    decorators = [check_perms(request)]

    def index(self):
        form = forms.DCSelect()
        form.data_center.choices = helper.gather_dc_choices()
        return render_template('lookup.html', form=form)

    @route('/servers', methods=['POST'])
    @route('/servers/<task_id>')
    def gather_servers(self, task_id=None):
        if request.method == 'POST':
            task = tasks.generate_account_server_list.delay(
                session.get('ddi'),
                session.get('token'),
                request.json.get('data_center'),
                request.json.get('lookup_type'),
                True
            )
            return jsonify(task_id=task.task_id)
        else:
            status = tasks.check_task_state(task_id)
            if status == 'PENDING':
                return jsonify(state=status, code=204)
            elif status == 'SUCCESS':
                account_id = tasks.get_task_results(task_id)
                account_data = g.db.accounts.find_one(
                    {'_id': ObjectId(account_id)}
                )
                mismatch = False
                if (
                    account_data.get('lookup_type') == 'host_server' and
                    len(account_data.get('servers')) !=
                    len(account_data.get('host_servers'))
                ):
                    mismatch = True

                return render_template(
                    '_server_breakdown.html',
                    data=account_data,
                    mismatch=mismatch,
                    task_id=task_id
                )

            return jsonify(state=status, code=500)

    @route('/servers/<task_id>/csv')
    def generate_server_csv(self, task_id):
        status = tasks.check_task_state(task_id)
        if status == 'SUCCESS':
            account_id = tasks.get_task_results(task_id)
            account_data = g.db.accounts.find_one(
                {'_id': ObjectId(account_id)}
            )
            template = render_template(
                'servers.csv',
                data=account_data
            )
            response = make_response(template)
            response.headers['Content-Type'] = 'application/csv'
            response.headers['Content-Disposition'] = (
                'attachment; filename="servers.csv"'
            )
            return response
        else:
            flash(
                'Task has not completed yet, so no CSV can be generated',
                'warning'
            )
            return redirect(url_for('BaseView:index'))

class ManagementView(FlaskView):
    route_base = '/manage'
    decorators = [check_perms(request)]

    @route('/regions', methods=['GET', 'POST'])
    def define_available_regions(self):
        settings = g.db.settings.find_one()
        form = forms.RegionSet()
        if request.method == 'POST' and form.validate_on_submit():
            region = Region(request.form)
            if region:
                action, data = '$push', region.__dict__
                if not settings.get('regions'):
                    action, data = '$set', [data]

                g.db.settings.update(
                    {
                        '_id': settings.get('_id')
                    }, {
                        action: {
                            'regions': data
                        }
                    }
                )
                flash('Region successfully added to system', 'success')
                return redirect(
                    url_for(
                        'ManagementView:define_available_regions'
                    )
                )
        else:
            if request.method == 'POST':
                flash(
                    'There was a form validation error, please '
                    'check the required values and try again.',
                    'error'
                )

        return render_template(
            'manage/manage_regions.html',
            form=form,
            settings=settings
        )

    @route('/<key>/<action>/<value>')
    def managed_data_actions(self, key, action, value):
        actions = ['activate', 'deactivate', 'remove']
        maps = {
            'regions': {
                'search': 'regions.abbreviation',
                'status': 'regions.$.active',
                'redirect': '/manage/regions',
                'flash_title': value.upper()
            }
        }
        if maps.get(key):
            options = maps.get(key)
            if action in actions:
                found = g.db.settings.find_one(
                    {
                        options.get('search'): value
                    }
                )
                if found:
                    if action == 'remove':
                        keys = options.get('search').split('.')
                        change = {'$pull': {keys[0]: {keys[1]: value}}}
                    else:
                        if action == 'activate':
                            change = {'$set': {options.get('status'): True}}
                        elif action == 'deactivate':
                            change = {'$set': {options.get('status'): False}}

                    g.db.settings.update(
                        {options.get('search'): value},
                        change
                    )
                    flash(
                        '%s was %sd successfully' % (
                            options.get('flash_title'),
                            action
                        ),
                        'success'
                    )
                else:
                    flash(
                        '%s was not found so no action taken' % value.title(),
                        'error'
                    )
            else:
                flash('Invalid action given so no action taken', 'error')
            return redirect(options.get('redirect'))
        else:
            flash('Invalid data key given so no action taken', 'error')
            return redirect('/')

""" API Classes """

class TaskAPI(Resource):
    def get(self, task_id):
        return jsonify(task_status=tasks.check_task_state(task_id))

class AccountAPI(Resource):
    def get(self, account_id, region):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        account_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'cache_expiration': {
                    '$gte': helper.get_timestamp()
                }
            }, {
                '_id': 0,
                'servers': 1
            }
        )
        return jsonify(data=account_data)

    def post(self, account_id, region):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        task_id = tasks.generate_account_server_list.delay(
            account_id,
            token,
            region,
            'host_server'
        )
        return jsonify(task_id=str(task_id))

    def delete(self, account_id, region):
        try:
            g.db.accounts.remove(
                {
                    'account_number': account_id,
                    'region': region
                }
            )
            return 'Request was successful', 204
        except:
            return helper.generate_error(
                'An error occured that prevented the delete to complete',
                500
            )

class ServerAPI(Resource):
    def put(self, account_id, region, server_id):
        """
            Update the account data with the new server, and return True
            or False as to whether the server is by itself on the hypervisor
            Save the data into cache as either way it will still reside on a
            host that has another server or by itself. The answer will be
            correct either way
        """
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        account_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'cache_expiration': {'$gte': helper.get_timestamp()}
            }
        )
        if not account_data:
            return helper.generate_error(
                'You must initialize before checking a server',
                400
            )

        check_server = g.db.accounts.find_one({'servers.id': server_id})
        if check_server:
            return helper.generate_error(
                'Server has been catalogued already',
                400
            )

        response = tasks.check_add_server_to_cache(
            token,
            region,
            account_id,
            server_id,
            account_data
        )
        return jsonify(duplicate=response)

    def get(self, account_id, region, server_id):
        token = tasks.check_auth_token(
            account_id,
            helper.check_for_token(request)
        )
        if not token:
            return helper.generate_error(
                'No authentication token provided, '
                'or authentication was unsuccessful',
                401
            )

        server_data = g.db.accounts.find_one(
            {
                'account_number': account_id,
                'region': region,
                'servers.id': server_id
            }, {
                'servers.$': 1
            }
        )
        if not server_data:
            return helper.generate_error(
                'Server was not found',
                404
            )

        check_host = server_data.get('servers')[0].get('host_id')
        host_servers = helper.generate_servers_on_same_host(
            account_id,
            region,
            check_host
        )
        duplicate = False
        if host_servers is not None and len(host_servers) > 1:
            duplicate = True

        return jsonify(duplicate=duplicate, host_servers=host_servers)
<|endoftext|>


<commit_before>once_set = set()

def once(key):
    if key in once_set:
        return False
    else:
        once_set.add(key)
        return True

already_complained = set()

def deprecated(replacement=None):
    def outer(func):
        def inner(*args, **kwargs):
            if func not in already_complained:
                if replacement is None:
                    print("\x1b[31;1mDeprecation warning: Don't use %s\x1b[0m" % (func.__name__))
                else:
                    print("\x1b[31;1mDeprecation warning: Use %s instead of %s\x1b[0m" % (replacement, func.__name__))
                already_complained.add(func)
            return func(*args, **kwargs)
        return inner
    return outer
<commit_msg>Use python's native warning system for deprecation warnings (#3324)<commit_after>import warnings

once_set = set()

def once(key):
    if key in once_set:
        return False
    else:
        once_set.add(key)
        return True

already_complained = set()

def deprecated(replacement=None):
    def outer(func):
        def inner(*args, **kwargs):
            if func not in already_complained:
                if replacement is None:
                    warnings.warn("Don't use %s" % (func.__name__), DeprecationWarning)
                else:
                    warnings.warn("Use %s instead of %s" % (replacement, func.__name__), DeprecationWarning)
                already_complained.add(func)
            return func(*args, **kwargs)
        return inner
    return outer
<|endoftext|>


<commit_before>import random
import characters
from time import sleep

print ("DRAGON SLAYER")
print "designed and developed by Cyrus Burt and Eric Matt" + "\n"
sleep(5)

#game intro
print "Welcome to the magical world of Kraagnord!"
sleep(5)
print "A strange and mystical world crawling with evil wizards, brave warriors and dragons!" + "\n"

#rules
print "and now for the rules."
sleep(3)
print "use the command Fight to slay evil creatures (but don't kill the good guys!)"
sleep(3)
print "use the command Get to take treasure and pick up things."
sleep(3)
print "use the command Look to see what is in the room or look at specific items in the room" + "\n\n\n\n\n"

#game start
name = raw_input("What is your name?: ")
name = str(name)
print "greetings, " + name + " I have a quest for you" + "\n"

print "here are your weapons" + "\n\n"

print "YOU GOT A SWORD!"
sleep(2)

todo1 = raw_input("what do you do now? : ")
if todo1 == "Explore":
   print "you look around and the wizard who gave you the sword" + "\n" "seems to have dissapeared"
elif todo1 == "Fight":
    print "You swing your sword and don't hit anything"
elif todo1 == "Get":
    print "You get 50 peices of gold that were hidden under a rock!"
elif todo1 == "Look":
    print "You see stuff in the room!"
else :
    print "I don't know how to " +todo1+ " because my programers didn't want to spend the time to make that work"

<commit_msg>Started to recode to work in python 3<commit_after>import random
import characters
from time import sleep

print ("DRAGON SLAYER")
print ("designed and developed by Cyrus Burt and Eric Matt" + "\n")
sleep(5)

#game intro
print ("Welcome to the magical world of Kraagnord!")
sleep(5)
print ("A strange and mystical world crawling with evil wizards, brave warriors and dragons!" + "\n")

#rules
print ("and now for the rules.")
sleep(3)
print ("use the command Fight to slay evil creatures (but don't kill the good guys!)")
sleep(3)
print ("use the command Get to take treasure and pick up things.")
sleep(3)
print ("use the command Look to see what is in the room or look at specific items in the room" + "\n\n\n\n\n")

#game start
name = raw_input("What is your name?: ")
name = str(name)
print ("greetings, " + name + " I have a quest for you" + "\n")

print ("here are your weapons" + "\n\n")

print ("YOU GOT A SWORD!")
sleep(2)

todo1 = raw_input("what do you do now? : ")
if todo1 == ("Explore"):
   print ("you look around and the wizard who gave you the sword" + "\n" "seems to have dissapeared")
elif todo1 == ("Fight"):
    print ("You swing your sword and don't hit anything")
elif todo1 == ("Get"):
    print ("You get 50 peices of gold that were hidden under a rock!")
elif todo1 == ("Look"):
    print ("You see stuff in the room!")
else :
    print ("I don't know how to " +todo1+ " because my programers didn't want to spend the time to make that work")

<|endoftext|>


<commit_before>import datetime, hashlib, random, re
from django.core.validators import *
from django.utils import timezone
from django.conf import settings
from django.db import models, transaction
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.template.loader import render_to_string

import app.constants
from app.email import send_email
from app.models.validators import *

SHA1_RE = re.compile('^[a-f0-9]{40}$')

class ShareZoneManager(models.Manager):
    def get_or_create(self, **kwargs):
        created = False
        try:
            share_zone = self.get(**kwargs)
        except ShareZone.DoesNotExist:
            share_zone = self.create(**kwargs)
            share_zone.save()
            created = True
        return [share_zone, created]

class ShareZone(models.Model):
    zip = models.CharField(max_length=9, default='', blank=False)

    objects = ShareZoneManager()

    class Meta:
        app_label = 'app'

    # TODO : Define get_tools method
    def get_tools(self):
        pass

class Address(models.Model):
    apt_num = models.CharField('apartment number', max_length=10, blank=True)
    street = models.CharField('street', max_length=50)
    city = models.CharField('city', max_length=50, validators=[AlphabetOnlyValidator()])
    county = models.CharField('county', max_length=50, default='', blank=True, validators=[AlphabetOnlyValidator()])
    state = models.CharField('state', max_length=2, default='', choices=app.constants.US_STATES)
    country = models.CharField('country', max_length=50, default='USA')
    zip = models.CharField('zip code', max_length=9, validators=[
        RegexValidator(regex='^\d{5,9}?$', message='should be 5 or 9 digits',
                       code='invalid_zip')])

    class Meta:
        app_label = 'app'

class UserManager(BaseUserManager):
    def _create_user(self, **extra_fields):
        # Separating the user fields and address fields for simplicity
        user_fields = self._get_fields(model='user', **extra_fields)
        address_fields = self._get_fields(model='address', **extra_fields)

        # ShareZone.zip is 9 characters wide for flexibility
        zip = (address_fields['zip'][:5]).ljust(9, '0')
        share_zone, created = ShareZone.objects.get_or_create(zip=zip)
        if created:
            share_zone.save(using=self._db)

        address = Address.objects.create(**address_fields)
        address.save(using=self._db)

        now = timezone.now()
        user_fields['email'] = self.normalize_email(user_fields['email'])
        user = self.model(date_joined=now, **user_fields)
        user.set_password(extra_fields['password1'])
        user.address = address
        user.share_zone = share_zone

        user.save(using=self._db)

        return user

    def create_user(self, **extra_fields):
        return self._create_user(**extra_fields)

    def _get_fields(self, model, **fields):
        _user_fields = ['date_joined', 'first_name', 'last_name', 'phone_num', 'email',
                        'pickup_arrangements', 'reputation']
        _address_fields = ['apt_num', 'street', 'city', 'county', 'state', 'country', 'zip']

        _fields = _user_fields
        if model == 'address':
            _fields = _address_fields

        sliced_fields = dict()
        for k, v in fields.items():
            if k in _fields:
                sliced_fields[k] = v

        return sliced_fields

class User(AbstractBaseUser):
    is_active = models.BooleanField('is active', default=False)
    date_joined = models.DateTimeField('Date joined', default=timezone.now)
    first_name = models.CharField('first name', max_length=30, validators=[AlphabetOnlyValidator()])
    last_name = models.CharField('last name', max_length=30, blank=True, validators=[AlphabetOnlyValidator()])
    phone_num = models.CharField('phone number', max_length=11, blank=True, validators=[
        RegexValidator(regex='^\d{9,10}$', message='should be 9 or 10 digits', code='invalid_phone')])
    email = models.EmailField('email address', unique=True, validators=[EmailValidator()])
    pickup_arrangements = models.TextField('pickup arrangements', max_length=100, blank=True)
    reputation = models.PositiveIntegerField('reputation', default=0, blank=True)
    send_reminders = models.BooleanField('send reminders', default=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']
    objects = UserManager()

    # Foreign keys
    address = models.ForeignKey(Address, unique=True)
    share_zone = models.ForeignKey(ShareZone)

    class Meta:
        app_label = 'app'

    def Update(self):
        pass

    def Register(self, Tool):
        pass

    def get_short_name(self):
        return self.first_name

    def get_full_name(self):
        full_name = self.first_name

        if self.last_name:
            full_name = full_name + ' ' + self.last_name

        return full_name

    def email_user(self, subject, message, from_addr):
        send_email(subject, message, [self.email], from_addr)

class RegistrationManager(models.Manager):
    def activate_user(self, activation_key):
        # Make sure the key we're trying conforms to the pattern of a
        # SHA1 hash; if it doesn't, no point trying to look it up in
        # the database.

        if SHA1_RE.search(activation_key):
            try:
                profile = self.get(activation_key=activation_key)
            except self.model.DoesNotExist:
                return False
            if not profile.activation_key_expired():
                user = profile.user
                user.is_active = True
                user.save()
                profile.activation_key = self.model.ACTIVATED
                profile.save()
                return user
        return False

    def create_inactive_user(self, site, send_email=True, **extra_fields):
        new_user = User.objects.create_user(**extra_fields)
        new_user.is_active = False
        new_user.save()

        registration_profile = self.create_profile(new_user)

        if send_email:
            registration_profile.send_activation_email(site)

        return new_user

    create_inactive_user = transaction.commit_on_success(create_inactive_user)

    def create_profile(self, user):
        salt = hashlib.sha1(str(random.random()).encode('utf-8')).hexdigest()[:5]
        seed = salt + user.email
        activation_key = hashlib.sha1(seed.encode('utf-8')).hexdigest()
        return self.create(user=user, activation_key=activation_key)

    def delete_expired_users(self):
        for profile in self.all():
            try:
                if profile.activation_key_expired():
                    user = profile.user
                    if not user.is_active:
                        user.delete()
                        profile.delete()
            except User.DoesNotExist:
                profile.delete()

class RegistrationProfile(models.Model):
    ACTIVATED = u"already_activated"

    user = models.ForeignKey(User, unique=True)
    activation_key = models.CharField(max_length=40)

    objects = RegistrationManager()

    class Meta:
        app_label = 'app'

    def activation_key_expired(self):
        if settings.ACCOUNT_ACTIVATION_DAYS != 0:
            expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
            return self.activation_key == self.ACTIVATED or (self.user.date_joined + expiration_date <= datetime_now())

    activation_key_expired.boolean = True

    def send_activation_email(self, site):
        template_name = 'email/account_activation.html'

        context = {'activation_key': self.activation_key,
                   'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                   'site': site, 'user': self.user}

        subject = 'Your New ToolShare Account'
        message = render_to_string(template_name, context)

        self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
<commit_msg>Fixed a bug in the regular expressions validating the user's phone number and zip code.<commit_after>import datetime, hashlib, random, re
from django.core.validators import *
from django.utils import timezone
from django.conf import settings
from django.db import models, transaction
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.template.loader import render_to_string

import app.constants
from app.email import send_email
from app.models.validators import *

SHA1_RE = re.compile('^[a-f0-9]{40}$')

class ShareZoneManager(models.Manager):
    def get_or_create(self, **kwargs):
        created = False
        try:
            share_zone = self.get(**kwargs)
        except ShareZone.DoesNotExist:
            share_zone = self.create(**kwargs)
            share_zone.save()
            created = True
        return [share_zone, created]

class ShareZone(models.Model):
    zip = models.CharField(max_length=9, default='', blank=False)

    objects = ShareZoneManager()

    class Meta:
        app_label = 'app'

    # TODO : Define get_tools method
    def get_tools(self):
        pass

class Address(models.Model):
    apt_num = models.CharField('apartment number', max_length=10, blank=True)
    street = models.CharField('street', max_length=50)
    city = models.CharField('city', max_length=50, validators=[AlphabetOnlyValidator()])
    county = models.CharField('county', max_length=50, default='', blank=True, validators=[AlphabetOnlyValidator()])
    state = models.CharField('state', max_length=2, default='', choices=app.constants.US_STATES)
    country = models.CharField('country', max_length=50, default='USA')
    zip = models.CharField('zip code', max_length=9, validators=[
        RegexValidator(regex='^\d{5}(\d{4})?$', message='should be 5 or 9 digits',
                       code='invalid_zip')])

    class Meta:
        app_label = 'app'

class UserManager(BaseUserManager):
    def _create_user(self, **extra_fields):
        # Separating the user fields and address fields for simplicity
        user_fields = self._get_fields(model='user', **extra_fields)
        address_fields = self._get_fields(model='address', **extra_fields)

        # ShareZone.zip is 9 characters wide for flexibility
        zip = (address_fields['zip'][:5]).ljust(9, '0')
        share_zone, created = ShareZone.objects.get_or_create(zip=zip)
        if created:
            share_zone.save(using=self._db)

        address = Address.objects.create(**address_fields)
        address.save(using=self._db)

        now = timezone.now()
        user_fields['email'] = self.normalize_email(user_fields['email'])
        user = self.model(date_joined=now, **user_fields)
        user.set_password(extra_fields['password1'])
        user.address = address
        user.share_zone = share_zone

        user.save(using=self._db)

        return user

    def create_user(self, **extra_fields):
        return self._create_user(**extra_fields)

    def _get_fields(self, model, **fields):
        _user_fields = ['date_joined', 'first_name', 'last_name', 'phone_num', 'email',
                        'pickup_arrangements', 'reputation']
        _address_fields = ['apt_num', 'street', 'city', 'county', 'state', 'country', 'zip']

        _fields = _user_fields
        if model == 'address':
            _fields = _address_fields

        sliced_fields = dict()
        for k, v in fields.items():
            if k in _fields:
                sliced_fields[k] = v

        return sliced_fields

class User(AbstractBaseUser):
    is_active = models.BooleanField('is active', default=False)
    date_joined = models.DateTimeField('Date joined', default=timezone.now)
    first_name = models.CharField('first name', max_length=30, validators=[AlphabetOnlyValidator()])
    last_name = models.CharField('last name', max_length=30, blank=True, validators=[AlphabetOnlyValidator()])
    phone_num = models.CharField('phone number', max_length=11, blank=True, validators=[
        RegexValidator(regex='^\d{10}(\d{1})?$', message='should be 10 or 11 digits', code='invalid_phone')])
    email = models.EmailField('email address', unique=True, validators=[EmailValidator()])
    pickup_arrangements = models.TextField('pickup arrangements', max_length=100, blank=True)
    reputation = models.PositiveIntegerField('reputation', default=0, blank=True)
    send_reminders = models.BooleanField('send reminders', default=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']
    objects = UserManager()

    # Foreign keys
    address = models.ForeignKey(Address, unique=True)
    share_zone = models.ForeignKey(ShareZone)

    class Meta:
        app_label = 'app'

    def Update(self):
        pass

    def Register(self, Tool):
        pass

    def get_short_name(self):
        return self.first_name

    def get_full_name(self):
        full_name = self.first_name

        if self.last_name:
            full_name = full_name + ' ' + self.last_name

        return full_name

    def email_user(self, subject, message, from_addr):
        send_email(subject, message, [self.email], from_addr)

class RegistrationManager(models.Manager):
    def activate_user(self, activation_key):
        # Make sure the key we're trying conforms to the pattern of a
        # SHA1 hash; if it doesn't, no point trying to look it up in
        # the database.

        if SHA1_RE.search(activation_key):
            try:
                profile = self.get(activation_key=activation_key)
            except self.model.DoesNotExist:
                return False
            if not profile.activation_key_expired():
                user = profile.user
                user.is_active = True
                user.save()
                profile.activation_key = self.model.ACTIVATED
                profile.save()
                return user
        return False

    def create_inactive_user(self, site, send_email=True, **extra_fields):
        new_user = User.objects.create_user(**extra_fields)
        new_user.is_active = False
        new_user.save()

        registration_profile = self.create_profile(new_user)

        if send_email:
            registration_profile.send_activation_email(site)

        return new_user

    create_inactive_user = transaction.commit_on_success(create_inactive_user)

    def create_profile(self, user):
        salt = hashlib.sha1(str(random.random()).encode('utf-8')).hexdigest()[:5]
        seed = salt + user.email
        activation_key = hashlib.sha1(seed.encode('utf-8')).hexdigest()
        return self.create(user=user, activation_key=activation_key)

    def delete_expired_users(self):
        for profile in self.all():
            try:
                if profile.activation_key_expired():
                    user = profile.user
                    if not user.is_active:
                        user.delete()
                        profile.delete()
            except User.DoesNotExist:
                profile.delete()

class RegistrationProfile(models.Model):
    ACTIVATED = u"already_activated"

    user = models.ForeignKey(User, unique=True)
    activation_key = models.CharField(max_length=40)

    objects = RegistrationManager()

    class Meta:
        app_label = 'app'

    def activation_key_expired(self):
        if settings.ACCOUNT_ACTIVATION_DAYS != 0:
            expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
            return self.activation_key == self.ACTIVATED or (self.user.date_joined + expiration_date <= datetime_now())

    activation_key_expired.boolean = True

    def send_activation_email(self, site):
        template_name = 'email/account_activation.html'

        context = {'activation_key': self.activation_key,
                   'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                   'site': site, 'user': self.user}

        subject = 'Your New ToolShare Account'
        message = render_to_string(template_name, context)

        self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
<|endoftext|>


<commit_before>import datetime, hashlib, random, re
from django.core.validators import *
from django.utils import timezone
from django.conf import settings
from django.db import models, transaction
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.template.loader import render_to_string

import app.constants
from app.email import send_email
from app.models.validators import *

SHA1_RE = re.compile('^[a-f0-9]{40}$')

class ShareZoneManager(models.Manager):
    def get_or_create(self, **kwargs):
        created = False
        try:
            share_zone = self.get(**kwargs)
        except ShareZone.DoesNotExist:
            share_zone = self.create(**kwargs)
            share_zone.save()
            created = True
        return [share_zone, created]

class ShareZone(models.Model):
    zip = models.CharField(max_length=9, default='', blank=False)

    objects = ShareZoneManager()

    class Meta:
        app_label = 'app'

    # TODO : Define get_tools method
    def get_tools(self):
        pass

class Address(models.Model):
    apt_num = models.CharField('apartment number', max_length=10, blank=True)
    street = models.CharField('street', max_length=50)
    city = models.CharField('city', max_length=50, validators=[AlphabetOnlyValidator()])
    county = models.CharField('county', max_length=50, default='', blank=True, validators=[AlphabetOnlyValidator()])
    state = models.CharField('state', max_length=2, default='', choices=app.constants.US_STATES)
    country = models.CharField('country', max_length=50, default='USA')
    zip = models.CharField('zip code', max_length=9, validators=[
        RegexValidator(regex='^\d{5,9}?$', message='should be 5 or 9 digits',
                       code='invalid_zip')])

    class Meta:
        app_label = 'app'

class UserManager(BaseUserManager):
    def _create_user(self, **extra_fields):
        # Separating the user fields and address fields for simplicity
        user_fields = self._get_fields(model='user', **extra_fields)
        address_fields = self._get_fields(model='address', **extra_fields)

        # ShareZone.zip is 9 characters wide for flexibility
        zip = (address_fields['zip'][:5]).ljust(9, '0')
        share_zone, created = ShareZone.objects.get_or_create(zip=zip)
        if created:
            share_zone.save(using=self._db)

        address = Address.objects.create(**address_fields)
        address.save(using=self._db)

        now = timezone.now()
        user_fields['email'] = self.normalize_email(user_fields['email'])
        user = self.model(date_joined=now, **user_fields)
        user.set_password(extra_fields['password1'])
        user.address = address
        user.share_zone = share_zone

        user.save(using=self._db)

        return user

    def create_user(self, **extra_fields):
        return self._create_user(**extra_fields)

    def _get_fields(self, model, **fields):
        _user_fields = ['date_joined', 'first_name', 'middle_name', 'last_name', 'phone_num', 'email',
                        'pickup_arrangements', 'reputation']
        _address_fields = ['apt_num', 'street', 'city', 'county', 'state', 'country', 'zip']

        _fields = _user_fields
        if model == 'address':
            _fields = _address_fields

        sliced_fields = dict()
        for k, v in fields.items():
            if k in _fields:
                sliced_fields[k] = v

        return sliced_fields

class User(AbstractBaseUser):
    is_active = models.BooleanField('is active', default=False)
    date_joined = models.DateTimeField('Date joined', default=timezone.now)
    first_name = models.CharField('first name', max_length=30, validators=[AlphabetOnlyValidator()])
    last_name = models.CharField('last name', max_length=30, blank=True, validators=[AlphabetOnlyValidator()])
    phone_num = models.CharField('phone number', max_length=11, blank=True, validators=[
        RegexValidator(regex='^\d{9,10}$', message='should be 9 or 10 digits', code='invalid_phone')])
    email = models.EmailField('email address', unique=True, validators=[EmailValidator()])
    pickup_arrangements = models.TextField('pickup arrangements', max_length=100, blank=True)
    reputation = models.PositiveIntegerField('reputation', default=0, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']
    objects = UserManager()

    # Foreign keys
    address = models.ForeignKey(Address, unique=True)
    share_zone = models.ForeignKey(ShareZone)

    class Meta:
        app_label = 'app'

    def Update(self):
        pass

    def Register(self, Tool):
        pass

    def get_short_name(self):
        return self.first_name

    def get_full_name(self):
        full_name = self.first_name

        if self.middle_name:
            full_name = full_name + ' ' + self.middle_name

        if self.last_name:
            full_name = full_name + ' ' + self.last_name

        return full_name

    def email_user(self, subject, message, from_addr):
        send_email(subject, message, [self.email], from_addr)

class RegistrationManager(models.Manager):
    def activate_user(self, activation_key):
        # Make sure the key we're trying conforms to the pattern of a
        # SHA1 hash; if it doesn't, no point trying to look it up in
        # the database.

        if SHA1_RE.search(activation_key):
            try:
                profile = self.get(activation_key=activation_key)
            except self.model.DoesNotExist:
                return False
            if not profile.activation_key_expired():
                user = profile.user
                user.is_active = True
                user.save()
                profile.activation_key = self.model.ACTIVATED
                profile.save()
                return user
        return False

    def create_inactive_user(self, site, send_email=True, **extra_fields):
        new_user = User.objects.create_user(**extra_fields)
        new_user.is_active = False
        new_user.save()

        registration_profile = self.create_profile(new_user)

        if send_email:
            registration_profile.send_activation_email(site)

        return new_user

    create_inactive_user = transaction.commit_on_success(create_inactive_user)

    def create_profile(self, user):
        salt = hashlib.sha1(str(random.random()).encode('utf-8')).hexdigest()[:5]
        seed = salt + user.email
        activation_key = hashlib.sha1(seed.encode('utf-8')).hexdigest()
        return self.create(user=user, activation_key=activation_key)

    def delete_expired_users(self):
        for profile in self.all():
            try:
                if profile.activation_key_expired():
                    user = profile.user
                    if not user.is_active:
                        user.delete()
                        profile.delete()
            except User.DoesNotExist:
                profile.delete()

class RegistrationProfile(models.Model):
    ACTIVATED = u"already_activated"

    user = models.ForeignKey(User, unique=True)
    activation_key = models.CharField(max_length=40)

    objects = RegistrationManager()

    class Meta:
        app_label = 'app'

    def activation_key_expired(self):
        if settings.ACCOUNT_ACTIVATION_DAYS != 0:
            expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
            return self.activation_key == self.ACTIVATED or (self.user.date_joined + expiration_date <= datetime_now())

    activation_key_expired.boolean = True

    def send_activation_email(self, site):
        template_name = 'email/account_activation.html'

        context = {'activation_key': self.activation_key,
                   'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                   'site': site, 'user': self.user}

        subject = 'Your New ToolShare Account'
        message = render_to_string(template_name, context)

        self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
<commit_msg>When the middle_name field was removed, the code was not refactored to remove references to it.<commit_after>import datetime, hashlib, random, re
from django.core.validators import *
from django.utils import timezone
from django.conf import settings
from django.db import models, transaction
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.template.loader import render_to_string

import app.constants
from app.email import send_email
from app.models.validators import *

SHA1_RE = re.compile('^[a-f0-9]{40}$')

class ShareZoneManager(models.Manager):
    def get_or_create(self, **kwargs):
        created = False
        try:
            share_zone = self.get(**kwargs)
        except ShareZone.DoesNotExist:
            share_zone = self.create(**kwargs)
            share_zone.save()
            created = True
        return [share_zone, created]

class ShareZone(models.Model):
    zip = models.CharField(max_length=9, default='', blank=False)

    objects = ShareZoneManager()

    class Meta:
        app_label = 'app'

    # TODO : Define get_tools method
    def get_tools(self):
        pass

class Address(models.Model):
    apt_num = models.CharField('apartment number', max_length=10, blank=True)
    street = models.CharField('street', max_length=50)
    city = models.CharField('city', max_length=50, validators=[AlphabetOnlyValidator()])
    county = models.CharField('county', max_length=50, default='', blank=True, validators=[AlphabetOnlyValidator()])
    state = models.CharField('state', max_length=2, default='', choices=app.constants.US_STATES)
    country = models.CharField('country', max_length=50, default='USA')
    zip = models.CharField('zip code', max_length=9, validators=[
        RegexValidator(regex='^\d{5,9}?$', message='should be 5 or 9 digits',
                       code='invalid_zip')])

    class Meta:
        app_label = 'app'

class UserManager(BaseUserManager):
    def _create_user(self, **extra_fields):
        # Separating the user fields and address fields for simplicity
        user_fields = self._get_fields(model='user', **extra_fields)
        address_fields = self._get_fields(model='address', **extra_fields)

        # ShareZone.zip is 9 characters wide for flexibility
        zip = (address_fields['zip'][:5]).ljust(9, '0')
        share_zone, created = ShareZone.objects.get_or_create(zip=zip)
        if created:
            share_zone.save(using=self._db)

        address = Address.objects.create(**address_fields)
        address.save(using=self._db)

        now = timezone.now()
        user_fields['email'] = self.normalize_email(user_fields['email'])
        user = self.model(date_joined=now, **user_fields)
        user.set_password(extra_fields['password1'])
        user.address = address
        user.share_zone = share_zone

        user.save(using=self._db)

        return user

    def create_user(self, **extra_fields):
        return self._create_user(**extra_fields)

    def _get_fields(self, model, **fields):
        _user_fields = ['date_joined', 'first_name', 'last_name', 'phone_num', 'email',
                        'pickup_arrangements', 'reputation']
        _address_fields = ['apt_num', 'street', 'city', 'county', 'state', 'country', 'zip']

        _fields = _user_fields
        if model == 'address':
            _fields = _address_fields

        sliced_fields = dict()
        for k, v in fields.items():
            if k in _fields:
                sliced_fields[k] = v

        return sliced_fields

class User(AbstractBaseUser):
    is_active = models.BooleanField('is active', default=False)
    date_joined = models.DateTimeField('Date joined', default=timezone.now)
    first_name = models.CharField('first name', max_length=30, validators=[AlphabetOnlyValidator()])
    last_name = models.CharField('last name', max_length=30, blank=True, validators=[AlphabetOnlyValidator()])
    phone_num = models.CharField('phone number', max_length=11, blank=True, validators=[
        RegexValidator(regex='^\d{9,10}$', message='should be 9 or 10 digits', code='invalid_phone')])
    email = models.EmailField('email address', unique=True, validators=[EmailValidator()])
    pickup_arrangements = models.TextField('pickup arrangements', max_length=100, blank=True)
    reputation = models.PositiveIntegerField('reputation', default=0, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']
    objects = UserManager()

    # Foreign keys
    address = models.ForeignKey(Address, unique=True)
    share_zone = models.ForeignKey(ShareZone)

    class Meta:
        app_label = 'app'

    def Update(self):
        pass

    def Register(self, Tool):
        pass

    def get_short_name(self):
        return self.first_name

    def get_full_name(self):
        full_name = self.first_name

        if self.last_name:
            full_name = full_name + ' ' + self.last_name

        return full_name

    def email_user(self, subject, message, from_addr):
        send_email(subject, message, [self.email], from_addr)

class RegistrationManager(models.Manager):
    def activate_user(self, activation_key):
        # Make sure the key we're trying conforms to the pattern of a
        # SHA1 hash; if it doesn't, no point trying to look it up in
        # the database.

        if SHA1_RE.search(activation_key):
            try:
                profile = self.get(activation_key=activation_key)
            except self.model.DoesNotExist:
                return False
            if not profile.activation_key_expired():
                user = profile.user
                user.is_active = True
                user.save()
                profile.activation_key = self.model.ACTIVATED
                profile.save()
                return user
        return False

    def create_inactive_user(self, site, send_email=True, **extra_fields):
        new_user = User.objects.create_user(**extra_fields)
        new_user.is_active = False
        new_user.save()

        registration_profile = self.create_profile(new_user)

        if send_email:
            registration_profile.send_activation_email(site)

        return new_user

    create_inactive_user = transaction.commit_on_success(create_inactive_user)

    def create_profile(self, user):
        salt = hashlib.sha1(str(random.random()).encode('utf-8')).hexdigest()[:5]
        seed = salt + user.email
        activation_key = hashlib.sha1(seed.encode('utf-8')).hexdigest()
        return self.create(user=user, activation_key=activation_key)

    def delete_expired_users(self):
        for profile in self.all():
            try:
                if profile.activation_key_expired():
                    user = profile.user
                    if not user.is_active:
                        user.delete()
                        profile.delete()
            except User.DoesNotExist:
                profile.delete()

class RegistrationProfile(models.Model):
    ACTIVATED = u"already_activated"

    user = models.ForeignKey(User, unique=True)
    activation_key = models.CharField(max_length=40)

    objects = RegistrationManager()

    class Meta:
        app_label = 'app'

    def activation_key_expired(self):
        if settings.ACCOUNT_ACTIVATION_DAYS != 0:
            expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
            return self.activation_key == self.ACTIVATED or (self.user.date_joined + expiration_date <= datetime_now())

    activation_key_expired.boolean = True

    def send_activation_email(self, site):
        template_name = 'email/account_activation.html'

        context = {'activation_key': self.activation_key,
                   'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                   'site': site, 'user': self.user}

        subject = 'Your New ToolShare Account'
        message = render_to_string(template_name, context)

        self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
<|endoftext|>