def test_user_subscribed_is_run_when_user_tier_is_changed_to_paid( self, user_subscribed, session): free_user = UserFactory(tier="free") free_user.plan = Plan.paid() session.add(free_user) session.commit() user_subscribed.assert_called_with(free_user.id, Plan.paid().id)
def test_after_commit_hooks_are_specific_to_a_session( self, user_subscribed, session, app): # What does this test prove? Well - we start by showing # the thing works and by setting up a an "after_commit" hook # on the session. (There SHOULD BE one session per request.) # The next request should NOT fire the "after_commit" hook # because it has a new session. IE - we are not leaking # Model instances across requests, and not firing subscribe # events for instances we didn't change free_user = UserFactory(tier="free") free_user.plan = Plan.paid() session.add(free_user) session.commit() session.expire_all() user_subscribed.assert_called_with(free_user.id, Plan.paid().id) user_subscribed.reset_mock() sess = db.create_scoped_session() free_user2 = UserFactory(tier="free", email="*****@*****.**") session.expunge(free_user2.plan) sess.add(free_user2) sess.commit() user_subscribed.assert_not_called() sess.remove()
def init_app(app): Config.init_app(app) with app.app_context(): from app.db import db from app.models import User from app.models import Plan db.init_app(app) db.create_all() # check if plans exist if len(Plan.query.all()) != 4: p1 = Plan(id=1, name='free', description='All the basic features of SupportService', cost=0) db.session.add(p1) p2 = Plan(id=2, name='bronze', description='Everything in free and email support.', cost=25) db.session.add(p2) p3 = Plan(id=3, name='silver', description='Everything in bronze and chat support.', cost=50) db.session.add(p3) p4 = Plan(id=4, name='gold', description='Everything in silver and 99.999% uptime SLA!', cost=50) db.session.add(p4) db.session.commit() # check if user exists if User.query.filter_by(email='*****@*****.**').first() is None: app.logger.info("Creating test user: [email protected] password: test") u = User(email='*****@*****.**') u.set_password('test') db.session.add(u) db.session.commit() else: app.logger.info("You can login with user: [email protected] password: test")
def add_plan(): for x in range(20): plan = Plan() plan.plan_name = "test plan" + str(x) plan.plan_day = random.randint(3, 999) plan.plan_total = random.randint(10, 9999) db.session.add(plan) db.session.commit()
def delete_stripe_customer(self) -> bool: if self.user.plan != Plan.free(): self.user.plan = Plan.free() self.unlink_from_plan(self.user.plan) stripe.Customer.delete(self.user.stripe_id) self.user.stripe_id = None self.user.stripe_payment_method = None return True
def test_user_unlink_from_plan_via_subscription(self): """Unlink a User from a plan based on change in their stripe subscription""" user = StripedUserFactory(tier="paid", stripe__payment_method="pm_card_visa") subscription = UserStripe(user)._retrieve_users_subscriptions( Plan.paid()) UserStripe(user).unlink_from_plan_via_subscription(subscription.id) assert UserStripe(user)._retrieve_users_subscriptions( Plan.paid()) is None assert user.plan == Plan.free()
def test_user_subscribed_is_run_when_user_tier_is_changed_to_paid( self, user_subscribed, session ): free_user = UserFactory(tier="free") UserUpdate( user=free_user, rels={"plan": {"data": {"type": "plan", "id": str(Plan.paid().id)}}}, ).update() db.session.commit() user_subscribed.assert_called_with(free_user.id, Plan.paid().id)
def test_user_unsubscribed(self, unsubscribe_successful, unsubscribe_not_required, session): """ User unsubscribes successfully """ user = SubscribedUserFactory(tier="paid", stripe__payment_method="pm_card_visa") user.plan = Plan.free() session.add(user) session.flush() UserStripe(user).unlink_from_plan(Plan.paid()) assert unsubscribe_successful.called_once assert not unsubscribe_not_required.called
def test_user_unsubscribed_is_run_when_user_tier_is_changed_to_free( self, user_unsubscribed, session ): user = UserFactory() db.session.add(user) db.session.flush() UserUpdate( user=user, rels={"plan": {"data": {"type": "plan", "id": str(Plan.free().id)}}}, ).update() db.session.commit() user_unsubscribed.assert_called_with(user.id, Plan.paid().id)
def test_delete_customer(self, app): """ Delete a Stripe Customer """ user = StripedUserFactory(tier="paid", email="*****@*****.**", stripe__payment_method="pm_card_visa") uss = UserStripe(user) uss.link_to_plan(Plan.paid()) customer_id = user.stripe_id UserStripe(user).delete_stripe_customer() cus = stripe.Customer.retrieve(customer_id) assert cus.deleted is True assert user.plan == Plan.free()
def link_to_plan(self, plan: Plan) -> None: uns = UserNotification(self.user) subscription: stripe.Subscription = None # this is an unrecoverable situation - we will need to set # up the users stripe id before this point - they should # not be able to get here without it. assert self.user.stripe_id is not None subscription = stripe.Subscription.create( customer=self.user.stripe_id, default_payment_method=self.user.stripe_payment_method, items=[{"plan": plan.stripe_id}], expand=["latest_invoice.payment_intent"], ) if subscription.latest_invoice.payment_intent.status == "succeeded": uns.subscribed_successfully() return if subscription.latest_invoice.payment_intent.status == "requires_action": uns.subscription_requires_action() else: uns.subscribed_failed() self.user.plan = Plan.free()
def updatePlanControler(self, request): if request.method == 'PUT': status = 200 [sessionid, response] = self.ulity.isEmptySession(request.session) if sessionid == None: response["message"] = Constant.FAIL_UPDATEPLAN return HttpResponse(content=simplejson.dumps(response), status=status) is_login = self.uservice.isLogin(sessionid) req = simplejson.loads(request.body) if is_login == Constant.ERROR_LOGIN_NOLOGIN: response['message'] = Constant.FAIL_UPDATEPLAN response['data'] = {} response['data']['error'] = is_login else: partner = req["partner"] partner_str = ','.join(partner) plan = Plan(PLAN_ID=req["planid"], PLAN_USER=is_login, PLAN_NAME=req["planname"], RUN_DATETIME=datetime.datetime.strptime( req["runtime"], '%Y-%m-%d %H:%M'), PARTNER=partner_str, PLACE=req["place"]) update_plan_message = self.planservice.updatePlan(plan) if update_plan_message != Constant.SUCCESS_UPDATEPLAN: response["message"] = Constant.FAIL_UPDATEPLAN response["data"] = {} response["data"]["error"] = update_plan_message else: response["message"] = Constant.SUCCESS_UPDATEPLAN response["planid"] = plan.PLAN_ID status = 200 return HttpResponse(content=simplejson.dumps(response), status=status)
def test_user_unsubscribed_is_run_when_user_tier_is_changed_to_free( self, user_unsubscribed, session): user = UserFactory() user.plan = Plan.free() session.add(user) session.commit() user_unsubscribed.assert_called_with(user.id)
def test_user_unsubscribed_but_didnt_need_to(self, unsubscribe_successful, unsubscribe_not_required, session): """User can't unsubscribe if they're not subscribed in the first place <taps forehead>""" user = StripedUserFactory(tier="free", stripe__payment_method="pm_card_visa") user.plan = Plan.free() session.add(user) session.flush() UserStripe(user).unlink_from_plan(Plan.paid()) assert not unsubscribe_successful.called assert unsubscribe_not_required.called_once
def update_plan(plan_id, data): if "code" not in data or "data" not in data: return False plan_id_test = Plan.generate_id_string(data["code"]) if plan_id_test != plan_id: return False model = get_plan(plan_id) # Get from cache if available # Get the UTC timestamp now = calendar.timegm(datetime.datetime.now().utctimetuple()) # Identify possible duplicates: while True: found = False for item in model.history: if item["id"] == now: now += 1 found = True if not found: break model.history.insert(0, { "id": now, "data": data["data"] }) # Hard limit to history: 10 itens if len(model.history) > 10: model.history.pop() model.put(use_cache=False, use_memcache=True) # Update cache too return model
def test_user_link_to_plan_via_subscription(self): """Link a User to a Plan based on a change in their stripe subscription""" user = StripedUserFactory( tier="paid", stripe__payment_method="pm_card_threeDSecure2Required") subscriptions = stripe.Subscription.list(plan=Plan.paid().stripe_id, customer=user.stripe_id) # this subscription is _NOT_ actually paid now, but we check in the event # listener - this method just makes sure the User's plan reflects the # subscription they'r paying for UserStripe(user).link_to_plan_via_subscription( subscriptions.data[0].id) assert user.plan == Plan.paid()
def test_striped_user_can_modify_plan(self, app, session): """ A user with a valid stripe_id is able to change their payment method """ app.test_client_class = TestClient user = StripedUserFactory(tier="free", stripe__payment_method="pm_card_visa") session.add(user) session.flush() plan_id = Plan.paid().id with app.test_client(user=user) as client: res = client.patch( "/account", json={ "data": { "type": "user", "attributes": {}, "relationships": { "plan": {"data": {"type": "plan", "id": str(plan_id)}} }, } }, ) assert res.status_code == 200 user = User.query.filter_by(uuid=user.uuid).first() assert user.tier == "paid"
def test_locate(): """ Convert a Json-API style locator ref to a python object """ p = Plan.paid() obj = locate({"type": "plan", "id": str(p.id)}) assert obj == p
def create_plan(): print(request.json) name = request.json.get('name') week = request.json.get('week') current = request.json.get('current') follow = request.json.get('follow') project_id = request.json.get('project_id') project = Project.query.filter_by(id=project_id).first() if project is None: return jsonify({'success':False,'error_code':-1,'errmsg':'project_id不存在'}) user = g.current_user plan = Plan(name=name,week=week,current=current,follow=follow,project_id=project.id,user_id=user.id,) db.session.add(plan) try: db.session.commit() except Exception as e: db.session.rollback() logging.error(f'添加数据库发生错误,已经回退:{e}') return jsonify({'success': False, 'error_code': -123, 'errmsg': '数据库插入错误,请查看日志'}) return jsonify({'success':True, 'error_code':0, })
def create_plan(data): if "code" not in data or "data" not in data: return False code = data["code"] plan_id = Plan.generate_id_string(code) if get_plan(plan_id): # Check in cache AND in database return False model = Plan( key=ndb.Key(Plan, plan_id), code=code, history=[{ "id": calendar.timegm(datetime.datetime.now().utctimetuple()), "data": data["data"] }] ) model.put(use_cache=False, use_memcache=True) return model
def populate(): """ Create DB Entries for Userland Cloud Plans""" for plan_name, plan in LIMITS.items(): p = Plan(**{"name": plan_name}, **plan) db.session.add(p) db.session.commit()
def test_user_async_unsubscribe(self, unlink_from_plan, session): user = UserFactory(tier="free", stripe_id="cust_12345") session.add(user) session.flush() plan = Plan.paid() user_unsubscribed(user.id, plan.id) assert unlink_from_plan.called_once_with(user, plan)
def get_plans(data): if "code" not in data: return [] code = Plan.generate_id_string(data["code"]) result = [] match = get_plan(code) if match: result.append(match) return result
def populate(): """ Create DB Entries for Holepunch Plans""" global LIMITS for plan_name, plan in LIMITS.items(): p = Plan(**{"name": plan_name}, **plan) db.session.add(p) db.session.commit()
def test_ld_user_hash(self): p = Plan(id=1, name='free') db.session.add(p) db.session.commit() u = User(email='*****@*****.**', plan_id=1) db.session.add(u) db.session.commit() emailHash = u.get_email_hash() userEmailHash = u.get_ld_user()['key'] self.assertEqual(userEmailHash, emailHash)
def test_user_fails_to_subscribe_no_card(self, _sf, _ss, _sfa, session): """ User couldn't subscribe because they didn't setup a card or stripe account""" user = UnstripedUserFactory() plan = Plan.paid() uss = UserStripe(user) session.add(user) session.flush() with pytest.raises(AssertionError): uss.link_to_plan(plan)
def test_user_can_change_relationship(self, session): free_user = UserFactory(tier="free") plan = Plan.paid() session.add(free_user) session.flush() user = UserUpdate( user=free_user, rels={"plan": {"data": {"type": "plan", "id": str(plan.id)}}}, ).update() assert user.plan == plan
def add_plan(): if current_user.email != '*****@*****.**': abort(403) form = InsertPlanForm() if form.validate_on_submit(): plan = Plan(name=form.name.data, req_short=form.req_short.data, req_full=form.req_full.data, benefits_short=form.benefits_short.data, benefits_full=form.benefits_full.data, application=form.application.data, website=form.website.data, kw1=form.kw1.data, kw2=form.kw2.data, kw3=form.kw3.data, kw4=form.kw4.data, kw5=form.kw5.data) db.session.add(plan) db.session.commit() flash('Plan added successfully.', 'success') return redirect(url_for('add_plan')) else: return render_template('insertplan.html', title='Insert Plan', form=form)
def test_user_fails_to_subscribe_decline( self, subscribed_successfully, subscribed_failed, subscription_requires_action, session, ): """ User's card was declined when paying """ # This is the 40000000341 card that will fail when a charge is initiated user = StripedUserFactory( tier="paid", stripe__payment_method="pm_card_chargeCustomerFail") session.add(user) session.flush() UserStripe(user).link_to_plan(user.plan) assert not subscribed_successfully.called assert not subscription_requires_action.called assert subscribed_failed.called_once assert user.plan == Plan.free()
def test_user_fails_to_subscribe_security( self, subscribed_failed, subscribed_successfully, subscription_requires_action, session, ): """ User payment failed becaues of additional security measures on their account """ user = StripedUserFactory( tier="paid", stripe__payment_method="pm_card_threeDSecure2Required") session.add(user) session.flush() UserStripe(user).link_to_plan(user.plan) assert not subscribed_successfully.called assert not subscribed_failed.called assert subscription_requires_action.called assert user.plan == Plan.free()
def test_user_subscribed_successfully( self, subscribed_successfully, subscribed_failed, subscription_requires_action, session, ): """ User subscribed sucessfully """ user = StripedUserFactory(tier="paid", stripe__payment_method="pm_card_visa") session.add(user) session.flush() # the user is a paid user when it is submitted to this job # immediately after a commit which changes it's plan_id # NOTE: this test does not actually change the user's plan UserStripe(user).link_to_plan(user.plan) assert not subscribed_failed.called assert not subscription_requires_action.called assert subscribed_successfully.called_once assert user.plan == Plan.paid()
def update_stripe_customer(self, updated_field) -> bool: if self.user.plan == Plan.free(): # we don't need to do anything return True uns = UserNotification(self.user) subscription = self._retrieve_users_subscriptions(self.user.plan) if subscription: if updated_field == "stripe_payment_method": stripe.Subscription.modify( subscription.id, default_payment_method=self.user.stripe_payment_method, ) return True else: uns.unsubscribe_required() return False else: raise UserError( detail="User #{user_id} has no subscription and is not on free plan" )
def addplan(): form = InsertPlanForm() if form.validate_on_submit(): plan = Plan(name=form.name.data, req_short=form.req_short.data, req_full=form.req_full.data, benefits_short=form.benefits_short.data, benefits_full=form.benefits_full.data, application=form.application.data, website=form.website.data, kw1=form.kw1.data, kw2=form.kw2.data, kw3=form.kw3.data, kw4=form.kw4.data, kw5=form.kw5.data, kw6=form.kw6.data) db.session.add(plan) db.session.commit() flash('Plan added successfully.') return redirect(url_for('addplan')) else: return render_template('insertplan.html', form=form)
def test_unstriped_user_cannot_modify_plan(self, app, session): """ The user can update plan id only if paymenet method and customer id are set. They cannot be set in the same request.""" app.test_client_class = TestClient user = UnstripedUserFactory() session.add(user) session.flush() plan_id = Plan.paid().id with app.test_client(user=user) as client: res = client.patch( "/account", json={ "data": { "type": "user", "relationships": { "plan": {"data": {"type": "plan", "id": str(plan_id)}} }, } }, ) assert res.status_code == 422
def get_all_hub_plans_of_plan_type(hub=None, plan_type=None): """ Return all hub plans of a particular hub and whose plan is of given plan_type """ query = and_() if plan_type: query = and_(Plan.type == plan_type) # get all plans of a given plan_type plans = Plan.find(query) res = list() for plan in plans: query = and_(HubPlan.plan == plan) if isinstance(hub, Hub): query = and_(query, HubPlan.hub == hub) hub_plans = HubPlan.find(query) res.extend(hub_plans) return res
def post(self, section, page=None): reply = {'success': True } ######################################################## ### Index ######################################################## ### TimeLIne if section == 'timeline': reply['timeline'] = self.get_timeline() ######################################################## ### Requests elif section == 'requests': reply['requests'] = self.get_schedule() elif section == 'request': ### Fetch Request if page == 'fetch': fppID = self.request.get("fppID") if not fppID: reply['error'] = 'No fppID' else: if fppID == '0': t = time.time() d = datetime.datetime.fromtimestamp(t - t % (60 *15) ) dic = { 'callsign': self.request.cookies['sessIdent'] , 'email': '', 'dep': '', 'dep_date': d.strftime(conf.MYSQL_DATETIME), 'dep_atc': '', 'arr': '', 'arr_date': '', 'arr_atc': '', 'comment': '', 'fppID': '0' } else: f = db.get( db.Key(fppID) ) dic = { 'callsign': f.callsign, 'email': 'email', 'dep': f.dep, 'dep_date': f.dep_date.strftime(conf.MYSQL_DATETIME), 'dep_atc': f.dep_atc, 'arr': f.arr, 'arr_date': f.arr_date.strftime(conf.MYSQL_DATETIME), 'arr_atc': f.arr_atc, 'comment': f.comment, 'fppID': str(f.key()), } reply['fpp'] = dic ################### ### Edit Request elif page == 'edit': fppID = self.request.get("fppID") if not fppID: reply['error'] = 'No fppID' else: callsign = self.request.get("callsign") if fppID == '0': fp = FPp(callsign = callsign) subject = 'New FP: %s' % callsign else: subject = 'Edit FP: %s' % callsign fp = db.get( db.Key(fppID) ) fp.cookie = self.request.cookies['sessID'] fp.callsign = callsign fp.dep = self.request.get("dep") fp.dep_date = self.get_date(self.request.get("dep_date"), self.request.get("dep_time")) fp.dep_atc = self.request.get("dep_atc") fp.arr = self.request.get("arr") fp.arr_date = self.get_date(self.request.get("arr_date"), self.request.get("arr_time")) fp.arr_atc = self.request.get("arr_atc") fp.comment = self.request.get("comment") fp.email = self.request.get("email") fp.put() reply['fppID'] = str(fp.key()) mail.send_mail( sender = conf.EMAIL, to = "Dev <*****@*****.**>", subject = subject, body = "Fp edited" ) ################### ### Delete Request elif page == 'delete': fppID = self.request.get("fppID") if not fppID: reply['error'] = 'No fppID' fp = db.get( db.Key(fppID) ) fp.delete() ######################################################## ### Crew elif section == 'crew': if 'sessID' in self.request.cookies: sessID = self.request.cookies['sessID'] if page == 'edit': crew = db.get( db.Key(sessID) ) crew.name = self.request.get('name') crew.email = self.request.get('email') crew.callsign = self.request.get('callsign') crew.cvs = self.request.get('cvs') crew.irc = self.request.get('irc') crew.forum = self.request.get('forum') crew.wiki = self.request.get('wiki') crew.pilot = False if self.request.get('pilot') == '' else True crew.atc = False if self.request.get('atc') == '' else True crew.fgcom = False if self.request.get('fgcom') == '' else True crew.location = self.request.get('location') crew.put() reply['crew+saved'] = True cook_str = 'sessIdent=%s; expires=Fri, 31-Dec-2020 23:59:59 GMT; Path=/;' % crew.callsign self.response.headers.add_header( 'Set-Cookie', cook_str ) else: crew = db.get( db.Key(sessID) ) reply['crew'] = [{'name': crew.name, 'email': crew.email, 'callsign': crew.callsign, 'cvs': crew.cvs, 'forum': crew.forum, 'irc': crew.irc, 'wiki': crew.wiki, 'pilot': crew.pilot, 'atc': crew.atc, 'fgcom': crew.fgcom, 'date_created': crew.date_created.strftime(conf.MYSQL_DATETIME), 'location': crew.location, 'ident': crew.ident }] ######################################################## ### Airpots elif section == 'airports': search = self.request.get("search") reply['airports'] = [] if not search: pass else: search = search.upper() reply['search'] = search for icao in airports: ss = icao + ' ' + airports[icao] if ss.upper().find(search) > -1: reply['airports'].append({'icao': icao, 'airport': airports[icao]}) ######################################################## ### Plans elif section == 'plans': col_len = -1 q = Plan.all() plans = q.fetch(1000) ret = [] for p in plans: route = json.loads(p.route) ret.append({'dep': p.dep, 'dest': p.dest, 'cruise': p.cruise, 'route': route, 'planID': str(p.key())}) if len(route) > col_len: col_len = len(route) reply['plans'] = ret reply['col_len'] = col_len elif section == 'plan': planID = '0' if page == 'edit': xml_str = self.request.get("xml") if planID == '0': data = self.parse_plan_xml(xml_str) plan = Plan() plan.xml = xml_str plan.dep = data['dep'] plan.dest = data['dest'] plan.route = json.dumps(data['route']) plan.put() reply['planID'] = str(plan.key()) ######################################################## ### Return Data ret_type = self.request.get('retDataType') if ret_type: if ret_type == 'schedule': reply['schedule'] = self.get_schedule() if ret_type == 'timeline': reply['timeline'] = self.get_timeline() ######################################################## ### Send self.response.headers.add_header('Content-Type','text/plain') self.response.out.write(json.dumps(reply))
def process_data_of_hub(hub, data, date_of_crawl=None): """ Process data given by cobot api """ # check if date of crawl is set or not # if not then set it with current date if date_of_crawl is None: date_of_crawl = get_current_date_str() for index, membership_data in enumerate(data): try: # preprocess a membership data in a model suitable # form m_data = preprocess_membership_data(membership_data) # check user exists or not if not create user else get it's # instance user = User.create_or_get(**m_data["user"]) # check membership exists or not if not create membership else # get it's instance membership = Membership.create_or_get(**m_data['membership']) # assign a hub to this membership if not else do nothing membership.assign_hub(hub) # assign a user to this membership if not else do nothing membership.assign_user(user) # check plan exists or not if not create plan else get it's # instance plan = Plan.create_or_get(**m_data['plan']) # check hub_plan exists or not if not create hub_plan else get # it's instance context = { 'hub': hub, 'plan': plan } hub_plan = HubPlan.create_or_get(**context) # check if plan of a membership changed or not if is_membership_plan_changed(membership, hub_plan): # if plan changed then set end_date of last active plan of # a membership as date_of_crawl, if any last_membership_plan = set_end_date_of_last_membership_plan( membership, date_of_crawl) # create a new membership plan instance context = { 'membership': membership, 'hub_plan': hub_plan, 'start_date': get_date_obj_from_str(date_of_crawl) } # and, also set `start_date` of membership plan depending upon # last_membership_plan existence if not last_membership_plan: context['start_date'] = \ m_data['membership']['confirmed_at'] # create a new membership plan membership_plan = MembershipPlan.create(**context) else: # nothing to do pass # check if membership ended or not and, if yes set canceled_to date # of membership and also set end_date of last membership_plan of # this membership_plan m_canceled_date = get_date_obj_from_str( membership_data['canceled_to']) membership.set_canceled_date(m_canceled_date) except Exception as e: logger.error(e, exc_info=True) logger.info("Total {0} Memberships processed on {1} of hub {2}".format( len(data), date_of_crawl, hub.name))