Exemplo n.º 1
0
def login(request, requestDict, no_recaptcha=False):
    """ 
    This combines Django's authenticate and login functions.
    The request.POST must contain a username and password.

    If authentication is successful, account is updated_locally
    and adds the appropriate data to the request so that the user/
    account is recognized to be logged in.
    
    This will also cache some of the store's info in the session.
    Also checks if the store is active or not.
    
    Returns an Account object if the account subscription is active 
    and username and passwords are good. Otherwise, 0 if bad login 
    credentials (wrong pass or pointer to store does not exist) 
    and 1 if subscription is not active,
    2 if employee but no access, 3 if employee is still pending,
    4 if RECAPTCHA_TOKEN in session and recaptcha response fails.
    """
    # first check if the request is already logged in
    if request.session.get('account'):
        return request.session.get('account')

    # now check for recaptcha
    if not no_recaptcha and RECAPTCHA_TOKEN in request.session and\
        request.session[RECAPTCHA_TOKEN] >= RECAPTCHA_ATTEMPTS:
        is_valid = recaptcha.submit(
            request, requestDict['recaptcha_challenge_field'],
            requestDict['recaptcha_response_field']).is_valid
        if not is_valid:
            return 4

    # note that email is the same as username
    # email needs to be stripped and lowered
    res = account_login(requestDict['username'].strip().lower(),
                        requestDict['password'])

    if res and "error" not in res:
        # correct login credentials - remove recaptcha token if exist
        if not no_recaptcha:
            recaptcha.login_success(request.session, requestDict['username'])

        account = Account(**res)
        account.fetch_all()

        # If the Account has both a Store and Employee object,
        # log the user in as the Store owner - not employee
        store = None
        if account.Store:
            store = account.store
            account_type = "store"
        elif account.Employee:
            store = account.employee.get("store")
            employee = account.employee
            account_type = "employee"

        # if the User object has a store then we are good to go
        if store:
            store.fetch_all()

            # check if employee with no access level or still pending
            if account_type == "employee":
                if employee.status == PENDING:
                    return 3
                elif not store.has_access(account):
                    return 2

            settings = store.get("settings")
            subscription = store.get("subscription")

            if store.get('active'):
                request.session[SESSION_KEY] = res.get('sessionToken')

                # load all cache data!
                # IMPORTANT for parse.comet.receive to work properly
                # reason is that if user stays in 1 page, not all
                # cache data is loaded and things go wrong-
                # e.g. sending message from window 1 does not update
                # the message count in window 2
                request.session['subscription'] = subscription
                request.session['settings'] = settings
                request.session['store'] = store
                request.session['account'] = account

                if account_type == "employee":
                    request.session['employee'] = employee

                SESSION.load_all(request.session)

                # If value is None, the session reverts to using
                # the global session expiry policy.
                if "stay_in" in requestDict and PRODUCTION_SERVER:
                    request.session.set_expiry(None)
                # If value is 0, the user's session cookie will
                # expire when the user's Web browser is closed.
                else:
                    request.session.set_expiry(0)

                return account
            else:
                return 1
        else:
            if not no_recaptcha:
                recaptcha.login_fail(request.session, requestDict['username'])
            return 0
    else:
        if not no_recaptcha:
            recaptcha.login_fail(request.session, requestDict['username'])
        return 0
Exemplo n.º 2
0
def sign_up(request):
    """
    Creates User, store, subscription, and settings objects.
    """
    # renders the signup page on GET and returns a json object on POST.
    data = {'sign_up_nav': True}

    if request.method == 'POST':
        # this conversion to a regular dictionay is important
        postDict = request.POST.dict()

        from_associated_account = False
        # check if this post is from the associated account dialog
        # if it is then skip form validations
        aaf_nonce_id = postDict.get('aaf-nonce')
        aaf_account_id = postDict.get('aaf-account_id')
        if len(aaf_nonce_id) > 0 and len(aaf_account_id) > 0:
            aa_nonce = AssociatedAccountNonce.objects.filter(\
                id=aaf_nonce_id, account_id=aaf_account_id)
            if len(aa_nonce) > 0 and aa_nonce[0].verified:
                aa_nonce[0].delete()
                from_associated_account = True

        # some keys are repeated so must catch this at init
        store_form = StoreSignUpForm(request.POST)
        store_location_form = StoreLocationForm(request.POST)
        account_form = AccountSignUpForm(request.POST)

        cats = postDict.get("categories")
        category_names = None
        if cats and len(cats) > 0:
            category_names = cats.split("|")[:-1]
            # make sure that there are only up to 2 categories
            while len(category_names) > 2:
                category_names.pop()
            data["category_names"] = category_names

        if not from_associated_account:
            all_forms_valid = store_form.is_valid() and\
                store_location_form.is_valid() and account_form.is_valid()
        else:
            all_forms_valid = True

        if all_forms_valid:
            # check if email already taken here to handle the case where
            # the user already has a patron/employee account
            # but also want to sign up for a Store account
            if hasattr(account_form, "associated_account"):
                aa = account_form.associated_account
                aan = AssociatedAccountNonce.objects.create(\
                    account_id=aa.objectId)
                return HttpResponse(json.dumps({"associated_account":\
                    aa.objectId, "associated_account_nonce":aan.id,
                    "email": aa.email, "code": 0}),
                    content_type="application/json")
            #########################################################

            # create store
            store = Store(**postDict)
            # set defaults for these guys to prevent
            # ParseObjects from making parse calls repeatedly
            store.punches_facebook = 1
            store.set("rewards", [])
            store.set("categories", [])
            if category_names:
                for name in category_names:
                    alias = Category.objects.filter(name__iexact=name)
                    if len(alias) > 0:
                        store.categories.append({
                            "alias": alias[0].alias,
                            "name": name
                        })

            # create settings
            settings = Settings(Store=store.objectId)
            store.set('settings', settings)

            # create account
            if not from_associated_account:
                account = Account(**postDict)
                # username = email
                # we should be doing this in the form but ehh
                account.set("username", postDict['email'].strip().lower())
                account.set("email", postDict['email'].strip().lower())
                account.set_password(postDict.get('password'))
            else:
                account =\
                    Account.objects().get(objectId=aaf_account_id)

            account.set("store", store)

            # create subscription
            subscription = Subscription()
            subscription.subscriptionType = 0
            subscription.date_last_billed = timezone.now()
            subscription.create()

            # create settings
            settings.create()

            # create store
            store.Settings = settings.objectId
            store.Subscription = subscription.objectId
            store.create()

            # add the pointer to the created store
            settings.Store = store.objectId
            settings.update()
            subscription.Store = store.objectId
            subscription.update()

            # create the store location
            store_location = StoreLocation(**postDict)
            # format the phone number
            store_location.store_timezone =\
                rputils.get_timezone(postDict.get("zip")).zone
            store_location.set("hours", [])
            # coordinates and neighborhood
            # the call to get map data is actually also in the clean
            full_address = " ".join(\
                store_location.get_full_address().split(", "))
            map_data = rputils.get_map_data(full_address)
            store_location.set("coordinates", map_data.get("coordinates"))
            store_location.set("neighborhood",
                store_location.get_best_fit_neighborhood(\
                    map_data.get("neighborhood")))
            store_location.phone_number =\
                format_phone_number(postDict["phone_number"])
            store_location.Store = store.objectId
            store_location.create()

            # add the StoreLocation to the relation
            store.store_locations = [store_location]
            store.update()

            # create account
            account.Store = store.objectId
            if not from_associated_account:
                account.create()
            else:
                account.update()

            # create the store ACL with the account having r/w access
            store.ACL = {
                "*": {
                    "read": True,
                    "write": True
                },
                account.objectId: {
                    "read": True,
                    "write": True
                },
            }
            store.owner_id = account.objectId
            store.update()

            # note that username has been fed the email
            # this shouldn't change anything though shouldn't matter
            # need to put username and pass in request
            postDict['username'] = account.username
            postDict['password'] = account.password

            # send matt and new user a pretty email.
            send_email_signup(account)

            # auto login
            user_login = login(request, postDict, no_recaptcha=True)
            if user_login != None:
                data = {"code": -1}
                # response to signup.js - not login returns
                # 0 - Associated account already exists
                # 2 - subscription is not active
                # 3 - success (login now)
                if type(user_login) is int:  # subscription not active
                    data['code'] = 2
                else:
                    # required for datetime awareness!
                    rputils.set_timezone(request, tz)
                    data['code'] = 3
                return HttpResponse(json.dumps(data),
                                    content_type="application/json")

    else:
        store_form = StoreSignUpForm()
        store_location_form = StoreLocationForm()
        account_form = AccountSignUpForm()

    data['store_form'] = store_form
    data['store_location_form'] = store_location_form
    data['account_form'] = account_form
    return render(request, 'public/signup.djhtml', data)
Exemplo n.º 3
0
    def processCometReceivedDict(session, postDict):
        employees_pending_list =\
            SESSION.get_employees_pending_list(session)
        employees_approved_list =\
            SESSION.get_employees_approved_list(session)
        messages_received_list =\
            SESSION.get_messages_received_list(session)
        redemptions_pending =\
            SESSION.get_redemptions_pending(session)
        redemptions_past =\
            SESSION.get_redemptions_past(session)

        #############################################################
        # FEEDBACKS_UNREAD ##################################
        newFeedback = postDict.get('newFeedback')
        if newFeedback:
            messages_received_ids =\
                [ fb.objectId for fb in messages_received_list ]
            m = Message(**newFeedback)
            if m.objectId not in messages_received_ids:
                messages_received_list.insert(0, m)

            session['messages_received_list'] =\
                messages_received_list

        #############################################################
        # FEEDBACK DELETED ##################################
        deletedFeedback = postDict.get("deletedFeedback")
        if deletedFeedback:
            fb = Message(**deletedFeedback)
            for i, mro in enumerate(messages_received_list):
                if fb.objectId == mro.objectId:
                    messages_received_list.pop(i)
                    break
            session['messages_received_list'] =\
                messages_received_list

        #############################################################
        # MESSAGE SENT ##################################
        # need to check if this new message is an original message
        # or a reply to a feedback (the message sent by the patron)!
        # also may increment the message count!
        newMessage = postDict.get("newMessage")
        if newMessage:
            messages_received_ids =\
                    [ fb.objectId for fb in messages_received_list ]
            messages_sent_list =\
                SESSION.get_messages_sent_list(session)
            messages_sent_ids =\
                [ msg.objectId for msg in messages_sent_list ]
            m = Message(**newMessage)
            if m.objectId not in messages_sent_ids and\
                m.message_type != FEEDBACK:
                messages_sent_list.insert(0, m)
                if 'message_count' in session:
                    session['message_count'] =\
                        int(session['message_count']) + 1
            # update an existing feedback
            if m.objectId in messages_received_ids and\
                m.message_type == FEEDBACK:
                for i, mrl in enumerate(messages_received_list):
                    if mrl.objectId == m.objectId:
                        messages_received_list.pop(i)
                        messages_received_list.insert(i, m)
                        break
            session['messages_received_list'] =\
                messages_received_list
            session['messages_sent_list'] = messages_sent_list

        #############################################################
        # EMPLOYEES_PENDING ##################################
        # must also check if employee is already approved!
        pendingEmployee = postDict.get("pendingEmployee")
        if pendingEmployee:
            employees_approved_ids =\
                [ emp.objectId for emp in employees_approved_list ]
            employees_pending_ids =\
                [ emp.objectId for emp in employees_pending_list ]
            e = Employee(**pendingEmployee)
            if e.objectId not in employees_pending_ids and\
                e.objectId not in employees_approved_ids:
                employees_pending_list.insert(0, e)

            session['employees_pending_list'] =\
                employees_pending_list

        #############################################################
        # EMPLOYEES APPROVED (pending to approved) #################
        approvedEmployee = postDict.get("approvedEmployee")
        if approvedEmployee:
            emp = Employee(**approvedEmployee)
            # first check if the employee is in the pending list
            # if not then check if it is already approved
            for i, emp_pending in\
                enumerate(employees_pending_list):
                if emp.objectId == emp_pending.objectId:
                    emp = employees_pending_list.pop(i)
                    emp.status = APPROVED
                    employees_approved_list.insert(0, emp)
                    break

            session['employees_pending_list'] =\
                employees_pending_list
            session['employees_approved_list'] =\
                employees_approved_list

        #############################################################
        # EMPLOYEES NEW (straight to approved) #################
        newEmployee = postDict.get("newEmployee")
        if newEmployee:
            employees_approved_ids =\
                [ emp.objectId for emp in employees_approved_list ]
            emp = Employee(**newEmployee)
            if emp.objectId not in employees_approved_ids:
                employees_approved_list.insert(0, emp)
                session['employees_approved_list'] =\
                    employees_approved_list

        #############################################################
        # EMPLOYEES DELETED/DENIED/REJECTED (pending/approved to pop)!
        deletedEmployee = postDict.get("deletedEmployee")
        if deletedEmployee:
            emp = Employee(**deletedEmployee)
            # check in approved emps
            for i, cop in enumerate(employees_approved_list):
                if cop.objectId == emp.objectId:
                    employees_approved_list.pop(i)
                    break

            # check in pending emps
            for i, cop in enumerate(employees_pending_list):
                if cop.objectId == emp.objectId:
                    employees_pending_list.pop(i)
                    break

            session['employees_approved_list'] =\
                employees_approved_list
            session['employees_pending_list'] =\
                employees_pending_list

        #############################################################
        # EMPLOYEE UPDATED PUNCHES
        updatedEmployeePunch = postDict.get("updatedEmployeePunch")
        if updatedEmployeePunch:
            u_emp = Employee(**updatedEmployeePunch)
            for emp in employees_approved_list:
                if u_emp.objectId == emp.objectId:
                    emp.set("lifetime_punches", u_emp.lifetime_punches)
                    break
            session['employees_approved_list'] =\
                employees_approved_list

        #############################################################
        # REDEMPTIONS PENDING
        ### Only added to cache if it has the store_location_id as
        ### active_store_location_id
        pendingRedemption = postDict.get("pendingRedemption")
        if pendingRedemption:
            rr = RedeemReward(**pendingRedemption)

            # store_location_id can be null for backwards compat
            if not rr.store_location_id or rr.store_location_id ==\
                session.get('active_store_location_id'):
                redemptions_pending_ids =\
                    [ red.objectId for red in redemptions_pending ]
                redemptions_past_ids =\
                    [ red.objectId for red in redemptions_past ]
                # need to check here if the redemption is new because
                # the dashboard that validated it will also receive
                # the validated redemption back.
                if rr.objectId not in redemptions_past_ids and\
                    rr.objectId not in redemptions_pending_ids:
                    redemptions_pending.insert(0, rr)

                session['redemptions_pending'] =\
                    redemptions_pending

        #############################################################
        # REDEMPTIONS APPROVED (pending to history)
        # Save cpu by skipping those that do not have the same
        # store_location_id as active_store_location_id
        approvedRedemption = postDict.get("approvedRedemption")
        if approvedRedemption:
            redemp = RedeemReward(**approvedRedemption)

            # store_location_id can be null for backwards compat
            if not redemp.store_location_id or redemp.store_location_id ==\
                session.get('active_store_location_id'):
                # check if redemp is still in pending
                for i, redem in enumerate(redemptions_pending):
                    if redem.objectId == redemp.objectId:
                        r = redemptions_pending.pop(i)
                        r.is_redeemed = True
                        r.updatedAt = redemp.updatedAt
                        redemptions_past.insert(0, r)
                        break
                # if not then check if it is in the history already
                # the above shouldn't happen!

                session['redemptions_pending'] =\
                    redemptions_pending
                session['redemptions_past'] =\
                    redemptions_past

        #############################################################
        # REDEMPTIONS DELETED ##############################
        # remove from pending (should not be in history!)
        # Save cpu by skipping those that do not have the same
        # store_location_id as active_store_location_id
        deletedRedemption = postDict.get("deletedRedemption")
        if deletedRedemption:
            redemp = RedeemReward(**deletedRedemption)

            # store_location_id can be null for backwards compat
            if not redemp.store_location_id or redemp.store_location_id ==\
                session.get('active_store_location_id'):
                # check if redemp is still in pending
                for i, redem in enumerate(redemptions_pending):
                    if redem.objectId == redemp.objectId:
                        redemptions_pending.pop(i)
                        break

                session['redemptions_pending'] =\
                    redemptions_pending

        #############################################################
        # STORE UPDATED ##############################
        updatedStore = postDict.get("updatedStore")
        if updatedStore:
            store = Store(**updatedStore)
            # have to add the image url manually
            store.thumbnail_image_url = updatedStore.get("thumbnail_image_url")
            store.cover_image_url = updatedStore.get("cover_image_url")
            # below here for backwards compat
            store.store_avatar_url = store.thumbnail_image_url
            session['store'] = store

        updatedStoreThumbnailName = postDict.get("updatedStoreThumbnailName")
        if updatedStoreThumbnailName:
            store = session['store']
            store.thumbnail_image = updatedStoreThumbnailName
            store.thumbnail_image_url = postDict.get(
                "updatedStoreThumbnailUrl")
            # below here for backwards compat
            store.store_avatar = store.thumbnail_image
            store.store_avatar_url = store.thumbnail_image_url
            session['store'] = store

        updatedStoreCoverName = postDict.get("updatedStoreCoverName")
        if updatedStoreCoverName:
            store = session['store']
            store.cover_image = updatedStoreCoverName
            store.cover_image_url = postDict.get("updatedStoreCoverUrl")
            session['store'] = store

        # this is in the settings tab in the dashboard but the field
        # is in the Store class
        updatedPunchesFacebook_int =\
            postDict.get("updatedPunchesFacebook_int")
        if updatedPunchesFacebook_int:
            store = session['store']
            store.punches_facebook = int(updatedPunchesFacebook_int)
            session['store'] = store

        #############################################################
        # STORE LOCATION UPDATED ##############################
        ### Note that this is also being used to insert new StoreLocations
        updatedStoreLocation = postDict.get("updatedStoreLocation")
        if updatedStoreLocation:
            store_location = StoreLocation(**updatedStoreLocation)
            session['store_locations'][store_location.objectId] =\
                store_location

            try:  # also update the store_timezone
                session['store_timezone'] =\
                    pytz.timezone(store_location.get('store_timezone'))
            except Exception:  # assign a default timezone
                session['store_timezone'] =\
                    pytz.timezone(TIME_ZONE)

        #############################################################
        # ACCOUNT UPDATED ##############################
        updatedAccount = postDict.get("updatedAccount")
        if updatedAccount:
            updatedAccountObject = Account(**updatedAccount)
            # need to make sure that these are the same accounts!
            if session['account'].objectId ==\
                updatedAccountObject.objectId:
                session['account'] = updatedAccountObject

        #############################################################
        # SUBSCRIPTION UPDATED ##############################
        updatedSubscription =\
            postDict.get("updatedSubscription")
        if updatedSubscription:
            subscription = Subscription(**updatedSubscription)
            store = session["store"]
            store.set('subscription', subscription)
            store.set('Subscription', subscription.objectId)
            session['subscription'] = subscription
            session['store'] = store

        #############################################################
        # SETTINGS UPDATED ##############################
        updatedSettings = postDict.get("updatedSettings")
        if updatedSettings:
            settings = Settings(**updatedSettings)
            store = session["store"]
            store.set('settings', settings)
            store.set("Settings", settings.objectId)
            session['settings'] = settings
            session['store'] = store

        #############################################################
        # REWARDS NEW ##############################
        newReward = postDict.get("newReward")
        if newReward:
            store = session['store']
            rewards = store.get("rewards")
            rewards_ids = [r['reward_id'] for r in rewards]
            if newReward['reward_id'] not in rewards_ids:
                rewards.append(newReward)
            store.rewards = rewards
            session['store'] = store

        #############################################################
        # REWARDS UPDATED ##############################
        updatedReward = postDict.get('updatedReward')
        if updatedReward:
            store = session['store']
            mod_rewards = store.get("rewards")
            for i, mreward in enumerate(mod_rewards):
                # [{"reward_name":"Free bottle of wine",
                # "description":"Must be under $25 in value",
                # "punches":10,"redemption_count":0,reward_id:0},]
                if updatedReward['reward_id'] == mreward['reward_id']:
                    if updatedReward.has_key("redemption_count"):
                        mod_rewards[i]['redemption_count'] =\
                            updatedReward['redemption_count']
                    if updatedReward.has_key("reward_name"):
                        mod_rewards[i]['reward_name'] =\
                            updatedReward['reward_name']
                    if updatedReward.has_key("punches"):
                        mod_rewards[i]['punches'] =\
                            updatedReward['punches']
                    if updatedReward.has_key("description"):
                        mod_rewards[i]['description'] =\
                            updatedReward['description']
                    break

            store.rewards = mod_rewards
            session['store'] = store

        #############################################################
        # REWARDS DELETED ##############################
        deletedReward = postDict.get("deletedReward")
        if deletedReward:
            store = session['store']
            rewards = store.get("rewards")
            rewards_ids = [r['reward_id'] for r in rewards]
            if deletedReward['reward_id'] in rewards_ids:
                for i, r in enumerate(rewards):
                    if r['reward_id'] == deletedReward['reward_id']:
                        rewards.pop(i)
                        break
            store.rewards = rewards
            session['store'] = store

        #############################################################
        # PATRONSTORE_COUNT ##################################
        patronStore_int = postDict.get('patronStore_int')
        if patronStore_int:
            patronStore_int = int(patronStore_int)
            session['patronStore_count'] = patronStore_int