class ACCOUNT_STATUS:
  """Enum(ish) of account status"""
  
  ENABLED = "enabled"
  PENDING_CREATE = "pending_create"
  DISABLED = "disabled"
  RANGE_OF_VALUES = [ENABLED,
                     PENDING_CREATE,
                     DISABLED] class Accounts(db.Model):
  email = db.EmailProperty(required=True)
  password = db.StringProperty(required=True, indexed=False);
  isEnabled = db.StringProperty(required=True, choices=ACCOUNT_STATUS.RANGE_OF_VALUES)
  creationDate = db.DateTimeProperty(auto_now_add=True, indexed=False)
  modifiedDate = db.DateTimeProperty(auto_now=True, indexed=False)
  accountType = db.StringProperty(required=True, 
                                  choices=set(ACCOUNT_TYPES), indexed=False) 
  paymentType = db.StringProperty(required=True, 
                                  choices=set(PAYMENT_TYPES), indexed=False)
  cookieKey = db.StringProperty(required=True, indexed=False)
  apiKey = db.StringProperty(required=True)

  trophyWidget = db.ReferenceProperty(required=True, reference_class=TrophyCase)
  pointsWidget = db.ReferenceProperty(required=True, reference_class=Points)
  rankWidget = db.ReferenceProperty(required=True, reference_class=Rank)
  notifierWidget = db.ReferenceProperty(reference_class=Notifier)
  milestoneWidget = db.ReferenceProperty(reference_class=Milestones)
  leaderWidget = db.ReferenceProperty(reference_class=Leaderboard)

  lastPayment = db.StringProperty(indexed=False)
  firstName = db.StringProperty(indexed=False)
  lastName = db.StringProperty(indexed=False)
  address = db.StringProperty(indexed=False)
  city = db.StringProperty(indexed=False)
  phoneNumber = db.StringProperty(indexed=False)
  state = db.StringProperty(indexed=False)
  country = db.StringProperty(indexed=False)
  comments = db.TextProperty(indexed=False)
  receiveMarketEmails = db.BooleanProperty(indexed=False)
  receiveAnalysisEmails = db.BooleanProperty(indexed=False)
  pointsTrackingPeriod = db.StringProperty(choices=set(["daily","weekly", "monthly"] ), indexed=False)
  lastPointsReset = db.DateTimeProperty(indexed=False)
  notifyOnPoints = db.BooleanProperty(default=True, indexed=False)
  # TODO do not use iconfinder's CDN, serve it up locally
  pointsImage = db.StringProperty(default="http://cdn4.iconfinder.com/data/icons/prettyoffice/128/add1-.png", indexed=False)
  loginImage = db.StringProperty(default="http://cdn1.iconfinder.com/data/icons/Hosting_Icons/128/secure-server-px-png.png", indexed=False) class TrophyCase(db.Model):
  backgroundColor = db.StringProperty( default="#eeeeff", indexed=False)
  borderThickness = db.IntegerProperty( default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty( default=500, indexed=False)
  width = db.IntegerProperty( default=270, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  # Title
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Trophy Case", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=20, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)
  # Date
  displayDate = db.BooleanProperty( default=True, indexed=False)
  dateColor = db.StringProperty( default="black", indexed=False)
  dateSize = db.IntegerProperty( default=8, indexed=False)
  dateFont = db.StringProperty( default="Arial", indexed=False)
  dateFloat = db.StringProperty( default="center", indexed=False)
  # Reason for getting badge
  displayReason = db.BooleanProperty( default=True, indexed=False)
  reasonColor = db.StringProperty( default="black", indexed=False)
  reasonSize = db.IntegerProperty( default=12, indexed=False)
  reasonFont = db.StringProperty( default="Arial", indexed=False)
  reasonFloat = db.StringProperty( default="center", indexed=False)

  # Random/Misc
  allowSorting = db.BooleanProperty( default=True, indexed=False)
  imageSize = db.IntegerProperty( default=100, indexed=False) 
  scrollable = db.BooleanProperty( default=False, indexed=False)

  # what to display if there is an empty case
  displayNoBadgesMessage = db.BooleanProperty( default=True, indexed=False)
  noBadgesMessage = db.StringProperty( default="Sorry, no badges yet!", indexed=False)
  noBadgesFont = db.StringProperty( default="Arial", indexed=False)
  noBadgesSize = db.IntegerProperty( default=12, indexed=False)
  noBadgesFloat = db.StringProperty( default="center", indexed=False)
  noBadgesColor = db.StringProperty( default="red", indexed=False) class Points(db.Model):
  backgroundColor = db.StringProperty( default="#EEEEFF", indexed=False)
  borderThickness = db.IntegerProperty( default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty( default=100, indexed=False)
  width = db.IntegerProperty( default=120, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  # Title
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Your Points", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=14, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)

  #displayPoints = db.BooleanProperty( default=True)
  pointsColor = db.StringProperty( default="black", indexed=False)
  pointsSize = db.IntegerProperty( default=14, indexed=False)
  pointsFont = db.StringProperty( default="Arial", indexed=False)
  pointsFloat = db.StringProperty( default="center", indexed=False) class Rank(db.Model):
  backgroundColor = db.StringProperty( default="#EEEEFF", indexed=False)
  borderThickness = db.IntegerProperty( default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty( default=100, indexed=False)
  width = db.IntegerProperty( default=120, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  # Title
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Your Ranking", indexed=False)
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=14, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)
  # Rank
  rankColor = db.StringProperty( default="black", indexed=False)
  rankSize = db.IntegerProperty( default=14, indexed=False)
  rankFont = db.StringProperty( default="Arial", indexed=False)
  rankFloat = db.StringProperty( default="center", indexed=False) class Notifier(db.Model):
  backgroundColor = db.StringProperty(default="#EEEEFF", indexed=False)
  borderThickness = db.IntegerProperty(default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty(default=160, indexed=False)
  width = db.IntegerProperty(default=150, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  # Title
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Congrats!", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=10, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)

  """http://docs.jquery.com/UI/Effects for different types""" 
  """'blind', 'clip', 'drop', 'explode', 'fold', 'puff', 'slide', 'scale', 'size', 'pulsate'."""
  exitEffect = db.StringProperty(default="fold", indexed=False)
  """'blind', 'clip', 'drop', 'explode', 'fold', 'puff', 'slide', 'scale', 'size', 'pulsate'."""
  entryEffect = db.StringProperty(default="drop", indexed=False)
  imageSize = db.IntegerProperty(default=100, indexed=False)

  # Note
  noteColor = db.StringProperty(default="#4488FF", indexed=False)
  displayNote = db.BooleanProperty( default=True, indexed=False)
  noteColor = db.StringProperty( default="#4488FF", indexed=False)
  noteSize = db.IntegerProperty( default=14, indexed=False)
  noteFont = db.StringProperty( default="Arial", indexed=False)
  noteFloat = db.StringProperty( default="center", indexed=False) class Leaderboard(db.Model):
  backgroundColor = db.StringProperty( default="#EEEEFF", indexed=False)
  alternateColor = db.StringProperty( default="#DDFFFF", indexed=False)
  borderThickness = db.IntegerProperty( default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty( default=1000, indexed=False)
  width = db.IntegerProperty( default=500, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  imageSize = db.IntegerProperty(default=constants.IMAGE_PARAMS.LEADER_SIZE, indexed=False)

  # Title
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Leaderboard", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=20, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)

  # Header
  headerBackgroundColor = db.StringProperty(default="#EEEEFF", indexed=False)
  displayHeader = db.BooleanProperty( default=True, indexed=False)
  headerColor = db.StringProperty( default="black", indexed=False)
  headerSize = db.IntegerProperty( default=20, indexed=False)
  headerFont = db.StringProperty( default="Arial", indexed=False)

  #Rank 
  rankColor = db.StringProperty(default="#4488FF", indexed=False)
  displayRank = db.BooleanProperty( default=True, indexed=False)
  rankColor = db.StringProperty( default="black", indexed=False)
  rankSize = db.IntegerProperty( default=25, indexed=False)
  rankFont = db.StringProperty( default="Arial", indexed=False)

  #Name 
  nameColor = db.StringProperty(default="#4488FF", indexed=False)
  displayName = db.BooleanProperty( default=True, indexed=False)
  nameColor = db.StringProperty( default="#4488FF", indexed=False)
  nameSize = db.IntegerProperty( default=14, indexed=False)
  nameFont = db.StringProperty( default="Arial", indexed=False)

  # Points
  pointsColor = db.StringProperty(default="#4488FF", indexed=False)
  displayPoints = db.BooleanProperty( default=True, indexed=False)
  pointsColor = db.StringProperty( default="#4488FF", indexed=False)
  pointsSize = db.IntegerProperty( default=20, indexed=False)
  pointsFont = db.StringProperty( default="Arial", indexed=False)
  pointsFloat = db.StringProperty( default="center", indexed=False)

  # what to display if there is an empty case
  displayNoUserMessage = db.BooleanProperty( default=True, indexed=False)
  noUserMessage = db.StringProperty( default="Check Back Soon!", indexed=False)
  noUserFont = db.StringProperty( default="Arial", indexed=False)
  noUserSize = db.IntegerProperty( default=20, indexed=False)
  noUserFloat = db.StringProperty( default="center", indexed=False)
  noUserColor = db.StringProperty( default="#FFF000", indexed=False) class Milestones(db.Model):
  backgroundColor = db.StringProperty( default="#eeeeff", indexed=False)
  borderThickness = db.IntegerProperty( default=1, indexed=False)
  borderColor = db.StringProperty( default="#4488FF", indexed=False)
  borderStyle = db.StringProperty( default="solid", indexed=False)
  height = db.IntegerProperty( default=500, indexed=False)
  width = db.IntegerProperty( default=270, indexed=False)
  hasRoundedCorners = db.BooleanProperty(default=False, indexed=False)
  # Title
  titleBackgroundColor = db.StringProperty(default="#4488FF", indexed=False)
  displayTitle = db.BooleanProperty( default=True, indexed=False)
  title = db.StringProperty( default="Badge Progress", indexed=False)
  titleColor = db.StringProperty( default="white", indexed=False)
  titleSize = db.IntegerProperty( default=20, indexed=False)
  titleFont = db.StringProperty( default="Arial", indexed=False)
  titleFloat = db.StringProperty( default="center", indexed=False)
  # Date
  displayDate = db.BooleanProperty( default=True, indexed=False)
  dateColor = db.StringProperty( default="black", indexed=False)
  dateSize = db.IntegerProperty( default=8, indexed=False)
  dateFont = db.StringProperty( default="Arial", indexed=False)
  dateFloat = db.StringProperty( default="center", indexed=False)
  # Reason for getting badge
  displayReason = db.BooleanProperty( default=True, indexed=False)
  reasonColor = db.StringProperty( default="black", indexed=False)
  reasonSize = db.IntegerProperty( default=12, indexed=False)
  reasonFont = db.StringProperty( default="Arial", indexed=False)
  reasonFloat = db.StringProperty( default="center", indexed=False)

  # Random/Misc
  allowSorting = db.BooleanProperty( default=True, indexed=False)
  imageSize = db.IntegerProperty( default=100, indexed=False) 
  scrollable = db.BooleanProperty( default=False, indexed=False) APP_NAME = "cloudcaptive-userinfuser" #os.environ['APPLICATION_ID']
APP_OWNER_EMAIL = "raj@cloudcaptive.com"
TEST_ACCOUNTS = ["raj@cloudcaptive.com","shanrandhawa@gmail.com","shan@cloudcaptive.com"]
ADMIN_ACCOUNT = "admin@" + APP_NAME + ".appspot.com"
DEBUG = True
ACCOUNT_TYPES = ["admin", "bronze", "silver", "gold", "platinum"]
PAYMENT_TYPES = ["free", "trial", "paid", "exempt"]
DEV_URL = "http://localhost:8080"
PRODUCTION_URL= "http://"+APP_NAME+".appspot.com"
SECURE_PRODUCTION_URL = "https://"+APP_NAME+".appspot.com"
CONSOLE_GET_WIDGET_DEV = "http://localhost:8080/api/1/getwidget"
CONSOLE_GET_WIDGET_PROD = "https://"+APP_NAME+".appspot.com/api/1/getwidget"
AES_ENCRYPTION_KEYNAME = "aes_encryption_key"
ENCRYPTION_KEYNAME = "encryption_key"
PROTECTED_DB_TYPES = ["Accounts", "Badges", "Users", "BadgeInstance", "BadgeImage", "TrophyCase", "Milestones", "Points", "Notifier", "Rank", "Leaderboard", "PassPhrase"]
  CLIENT_EVENT = ["signin",
             "logout",
             "dropaccount",
             "startpayments",
             "upgrade",
             "downgrade",
             "dropuser",
             "addbadge",
             "removebadge",
             "error",
             "viewanalytics",
             "viewbadges",
             "signup",
             "test"]
  API_EVENT = ["awardpoints",
             "awardbadge",
             "awardbadgepoints",
             "badgeawarded", # if required badge points met
             "removebadge",
             "viewwidget",
             "prefetchwidget",
             "clickbadge",
             "updateuser",
             "loginuser",
             "createuser",
             "getuserdata",
             "notify_badge",
             "notify_points"]
  SECRET_KEYNAME = "secret_log_key"
  PATH = '/logevents'
  SECRET_KEYNAME = "secret_update_key"
  PATH = '/updateaccount'
  DEFAULT_SIZE = 150
  LEADER_SIZE = 90 
  VALID_EXT_TYPES = ['png','jpg','jpeg','gif','PNG','JPG','JPEG','GIF']
  USER_AVATAR = "http://i.imgur.com/cXhDa.png"
  POINTS_IMAGE = "http://cdn1.iconfinder.com/data/icons/nuove/128x128/actions/edit_add.png"
  LOGIN_IMAGE = "http://www.iconfinder.com/icondetails/8794/128/cryptography_key_lock_log_in_login_password_security_icon" 
  NOT_AUTH = 1 # Not authorized error, either bad account or api key
  BADGE_NOT_FOUND = 2
  USER_NOT_FOUND = 3
  INTERNAL_ERROR = 4 
  BAD_ARGS = 5
  BAD_USER = 6
  ENABLED = "enabled"
  PENDING_CREATE = "pending_create"
  DISABLED = "disabled"
  RANGE_OF_VALUES = [ENABLED,
                     PENDING_CREATE,
                     DISABLED]
  CONSOLE_LOGIN = os.path.join(os.path.dirname(__file__), '../static/console_templates/login.html')
  CONSOLE_FORGOTTEN_PASSWORD = os.path.join(os.path.dirname(__file__), '../static/console_templates/forgot.html')
  CONSOLE_DASHBOARD =  os.path.join(os.path.dirname(__file__), '../static/console_templates/dashboard.html')
  CONSOLE_USERS =  os.path.join(os.path.dirname(__file__), '../static/console_templates/users.html')
  CONSOLE_SIGN_UP =  os.path.join(os.path.dirname(__file__), '../static/console_templates/signup_console.html')
  RENDER_TROPHY_CASE = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/trophy_case.html')
  RENDER_NOTIFIER = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/notifier.html')
  RENDER_MILESTONES = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/milestones.html')
  RENDER_POINTS = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/points.html')
  RENDER_RANK = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/rank.html')
  RENDER_LEADERBOARD = os.path.join(os.path.dirname(__file__), 'api/widgets/v1.0/leaderboard.html')
  COOKIE_EMAIL_PARAM = "key" # simply email, however, we don't want people their address is set in the cookie
  COOKIE_KEY_PARAM = "ssid" # same as the cookie_key param in our Accounts DB
  COOKIE_EXPIRATION = "esid" # expiration
  VALID_FOR_SECONDS = 86400 # make session valid for a day 
  POST_DATA = ""
  ACTIVATE_URL = ""
  REDIRECT_SIGNUP_SUCCESS = ""
  REDIRECT_SIGNUP_FAIL = ""
  REDIRECT_ACTIVATE_SUCCESS = ""
  REDIRECT_ACTIVATE_FAIL = ""
  REDIRECT_HOME = ""
  REDIRECT_SIGNUP = ""
    POST_DATA = "/signup"
    ACTIVATE_URL = "/signup"
    REDIRECT_SIGNUP_SUCCESS = "/html/signup_success.html"
    REDIRECT_SIGNUP_FAIL = "/html/signup_failed.html"
    REDIRECT_ACTIVATE_SUCCESS = "/html/activation_success.html"
    REDIRECT_ACTIVATE_FAIL = "/html/activation_fail.html"
    REDIRECT_HOME = "/html/index.html"
    REDIRECT_SIGNUP = "/html/signup.html"
    POST_DATA = SECURE_PRODUCTION_URL + "/signup" # need to use https URL for posting credentials
    ACTIVATE_URL = SECURE_PRODUCTION_URL + "/signup"
    REDIRECT_SIGNUP_SUCCESS = PRODUCTION_URL + "/html/signup_success.html"
    REDIRECT_SIGNUP_FAIL = PRODUCTION_URL + "/html/signup_failed.html"
    REDIRECT_ACTIVATE_SUCCESS = PRODUCTION_URL + "/html/activation_success.html"
    REDIRECT_ACTIVATE_FAIL = PRODUCTION_URL + "/html/activation_fail.html"
    REDIRECT_HOME = PRODUCTION_URL + "/html/index.html"
    REDIRECT_SIGNUP = PRODUCTION_URL + "/html/signup.html"
ADMINPASSWD = "u8u8u9i9i"
ADMINKEY = "u8u89i9i"
VALID_WIDGETS = ["trophy_case", "notifier", "milestones", "points", "leaderboard", "rank"]
WIDGETS_THAT_DONT_NEED_A_USER = ["milestones", "leaderboard"]
ANONYMOUS_USER = "__ui__anonymous__"
LOCAL_URL = "http://localhost:8080/"
MAX_BADGE_SIZE = 2<<16 # 128k
NOTIFIER_SIZE_DEFAULT = 180
NOT_RANKED = -1 # For unranked users
NUMBER_RANKED = "10000" #Anyone not in the top 10k is not ranked
TOP_USERS = "10"
class LOGGING:
class UPDATE:
class IMAGE_PARAMS:
class API_ERROR_CODES:
class ACCOUNT_STATUS:
class TEMPLATE_PATHS:
class WEB_ADMIN_PARAMS:
class WEB_SIGNUP_URLS: def generate_random_string(length = 8):
def camelcase_to_friendly_str(s):
def validEmail(email):
def account_login_required(handler_method):
  def check_login(self, *args):
def format_integer(number):
from serverside.constants import ACCOUNT_STATUS
from serverside.entities import memcache_db
from serverside.entities.accounts import Accounts
from serverside.entities.widgets import TrophyCase, Points, Rank, Notifier, \
  Leaderboard, Milestones
from serverside import constants 
from serverside.tools import utils
from serverside.dao import users_dao
import hashlib
import logging
import uuid
# Copyright (C) 2011, CloudCaptive
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
'''
Created on Feb 14, 2011

psuedo DAO methods

@author: shan
'''


def create_account(email, 
                   password, 
                   enable=False,
                   account_type="bronze",
                   payment_type="free"):
  """
  Creates an account with all the other needed dependencies properly initialized.
  """
  
  
  """
  Required:
  email = db.EmailProperty(required=True)
  password = db.StringProperty(required=True);
  isEnabled = db.StringProperty(required=True, choices=ACCOUNT_STATUS.RANGE_OF_VALUES)
  accountType = db.StringProperty(required=True, choices=set(ACCOUNT_TYPES)) 
  paymentType = db.StringProperty(required=True,choices=set(PAYMENT_TYPES))
  cookieKey = db.StringProperty(required=True)
  apiKey = db.StringProperty(required=True)
  trophyWidget = db.ReferenceProperty(required=True, reference_class=TrophyCase)
  pointsWidget = db.ReferenceProperty(required=True, reference_class=Points)
  rankWidget = db.ReferenceProperty(required=True, reference_class=Rank)
  """
  
  new_trophy_case = TrophyCase(key_name=email)
  memcache_db.save_entity(new_trophy_case, email)

  new_rank = Rank(key_name=email)
  memcache_db.save_entity(new_rank, email)


  new_points = Points(key_name=email)