def test_anonymous_user(self): condition_set = "gargoyle.builtins.UserConditionSet(auth.user)" switch = Switch.objects.create(key="test") switch = gargoyle["test"] switch.status = SELECTIVE switch.save() user = AnonymousUser() self.assertTrue(gargoyle.is_active("test", user)) switch.add_condition(condition_set=condition_set, field_name="percent", condition="1-10") self.assertFalse(gargoyle.is_active("test", user)) switch.clear_conditions(condition_set=condition_set) self.assertTrue(gargoyle.is_active("test", user)) switch.add_condition(condition_set=condition_set, field_name="is_anonymous", condition="1") self.assertTrue(gargoyle.is_active("test", user)) switch.add_condition(condition_set=condition_set, field_name="percent", condition="1-10") self.assertTrue(gargoyle.is_active("test", user))
def test_expiration(self): switch = Switch.objects.create(key="test") switch = gargoyle["test"] switch.status = DISABLED switch.save() self.assertFalse(gargoyle.is_active("test")) Switch.objects.filter(key="test").update(value={}, status=SELECTIVE) # cache shouldn't have expired self.assertFalse(gargoyle.is_active("test")) # in memory cache shouldnt have expired cache.delete(gargoyle.cache_key) self.assertFalse(gargoyle.is_active("test")) switch.status, switch.value = SELECTIVE, {} # Ensure post save gets sent gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get("/") self.assertTrue(gargoyle.is_active("test"))
def test_user(self): condition_set = "gargoyle.builtins.UserConditionSet(auth.user)" # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create(key="test", status=SELECTIVE) switch = gargoyle["test"] switch.add_condition(condition_set=condition_set, field_name="percent", condition="0-50") user = User(pk=5) self.assertTrue(gargoyle.is_active("test", user)) user = User(pk=8771) self.assertFalse(gargoyle.is_active("test", user)) switch.add_condition(condition_set=condition_set, field_name="is_staff", condition="1") user = User(pk=8771, is_staff=True) self.assertTrue(gargoyle.is_active("test", user)) user = User(pk=8771, is_superuser=True) self.assertFalse(gargoyle.is_active("test", user)) switch.add_condition(condition_set=condition_set, field_name="is_superuser", condition="1") user = User(pk=8771, is_superuser=True) self.assertTrue(gargoyle.is_active("test", user))
def test_exclusions(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', exclude=True, ) switch.add_condition( condition_set=condition_set, field_name='username', condition='foo', ) user = User(pk=5, username='******') self.assertFalse(gargoyle.is_active('test', user)) user = User(pk=8771, username='******') self.assertTrue(gargoyle.is_active('test', user))
def queue_apikey_updates(update_delay=86400, batch_size=50): """ Updates all Eve API elements in the database """ log = queue_apikey_updates.get_logger() if gargoyle.is_active('api-disableprocessing'): log.info("Backend processing disabled, exiting") return # Update all the eve accounts and related corps delta = timedelta(seconds=update_delay) log.info("Updating APIs older than %s" % (now() - delta)) if gargoyle.is_active('eve-cak'): accounts = EVEAccount.objects.filter(api_last_updated__lt=(now() - delta)).exclude(api_status__in=[API_STATUS_ACC_EXPIRED, API_STATUS_KEY_EXPIRED, API_STATUS_AUTH_ERROR]).order_by('api_last_updated')[:batch_size] else: accounts = EVEAccount.objects.filter(api_last_updated__lt=(now() - delta)).exclude(api_status__in=[API_STATUS_ACC_EXPIRED, API_STATUS_KEY_EXPIRED, API_STATUS_AUTH_ERROR]).exclude(api_keytype__gt=2).order_by('api_last_updated')[:batch_size] log.info("%s account(s) to update" % accounts.count()) for acc in accounts: log.debug("Queueing UserID %s for update" % acc.pk) if not acc.user: acc.delete() continue import_apikey.delay(api_key=acc.api_key, api_userid=acc.pk)
def test_expiration(self): switch = Switch.objects.create(key='test') switch = gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(gargoyle.is_active('test')) Switch.objects.filter(key='test').update(value={}, status=SELECTIVE) # cache shouldn't have expired self.assertFalse(gargoyle.is_active('test')) # in memory cache shouldnt have expired cache.delete(gargoyle.cache_key) self.assertFalse(gargoyle.is_active('test')) switch.status, switch.value = SELECTIVE, {} # Ensure post save gets sent gargoyle._post_save(sender=None, instance=switch, created=False) # any request should expire the in memory cache self.client.get('/') self.assertTrue(gargoyle.is_active('test'))
def test_is_active_email_in_get_data_match(self): data = {'email': '*****@*****.**'} qs = '?' + urlencode(data) request = self.request.get(qs) self.assertTrue(gargoyle.is_active(self.key_name, request)) data['email'] = '*****@*****.**' qs = '?' + urlencode(data) request = self.request.get(qs) self.assertTrue(gargoyle.is_active(self.key_name, request))
def test_disable(self): switch = Switch.objects.create(key='test') switch = gargoyle['test'] switch.status = DISABLED switch.save() self.assertFalse(gargoyle.is_active('test')) self.assertFalse(gargoyle.is_active('test', self.user))
def test_disable(self): switch = Switch.objects.create(key="test") switch = gargoyle["test"] switch.status = DISABLED switch.save() self.assertFalse(gargoyle.is_active("test")) self.assertFalse(gargoyle.is_active("test", self.user))
def test_global(self): condition_set = "gargoyle.builtins.UserConditionSet(auth.user)" switch = Switch.objects.create(key="test", status=SELECTIVE) switch = gargoyle["test"] self.assertTrue(gargoyle.is_active("test")) self.assertTrue(gargoyle.is_active("test", self.user)) switch.status = GLOBAL switch.save() self.assertTrue(gargoyle.is_active("test")) self.assertTrue(gargoyle.is_active("test", self.user))
def test_exclusions(self): condition_set = "gargoyle.builtins.UserConditionSet(auth.user)" switch = Switch.objects.create(key="test", status=SELECTIVE) switch = gargoyle["test"] switch.add_condition(condition_set=condition_set, field_name="percent", condition="0-50", exclude=True) switch.add_condition(condition_set=condition_set, field_name="username", condition="foo") user = User(pk=5, username="******") self.assertFalse(gargoyle.is_active("test", user)) user = User(pk=8771, username="******") self.assertTrue(gargoyle.is_active("test", user))
def get(self, request, *args, **kwargs): if not gargoyle.is_active('reddit', request): return HttpResponseNotFound() profile = request.user.get_profile() if profile.primary_character is None: messages.add_message(request, messages.ERROR, "Reddit account tagging requires a primary character before using. Please set one.") if EVEPlayerCharacter.objects.filter(eveaccount__user=self.request.user).count(): return HttpResponseRedirect(reverse('sso-primarycharacterupdate')) else: return HttpResponseRedirect(reverse('sso-profile')) profile.tag_reddit_accounts = not profile.tag_reddit_accounts profile.save() if profile.tag_reddit_accounts: tag = 'Enabled' else: tag = 'Disabled' messages.info(request, "Reddit account tagging is now %s" % tag) if profile.tag_reddit_accounts: name = profile.primary_character.name else: name = '' for acc in self.request.user.redditaccount_set.all(): from reddit.tasks import update_user_flair update_user_flair.delay(acc.username, name) return HttpResponseRedirect(reverse('sso-profile'))
def import_corp_members(key_id, character_id): """ This function pulls all corporation members from the EVE API using a director's API key. It'll add as much information as it can about the character. """ log = import_corp_members.get_logger() try: acc = EVEAccount.objects.get(pk=key_id) except EVEAccount.DoesNotExist: return # grab and decode /corp/MemberTracking.xml.aspx if gargoyle.is_active('eve-cak') and acc.api_keytype == API_KEYTYPE_CORPORATION: if not acc.has_access(11) and not acc.has_access(25): log.error('Key does not have access to MemberTrackingLimited or MemberTrackingExtended', extra={'data': {'key_id': key_id, 'character_id': character_id}}) return auth_params = {'keyid': acc.api_user_id, 'vcode': acc.api_key, 'characterID': character_id } if acc.has_access(25): auth_params['extended'] = 1 else: auth_params = {'userID': acc.api_user_id, 'apiKey': acc.api_key, 'characterID': character_id } try: char_doc = CachedDocument.objects.api_query('/corp/MemberTracking.xml.aspx', params=auth_params, no_cache=False, timeout=60) except DocumentRetrievalError: log.error('Error retreiving MemberTracking', exc_info=sys.exc_info(), extra={'data': {'keyid': acc.api_user_id, 'character': character_id}}) return pdoc = basic_xml_parse_doc(char_doc) if not 'eveapi' in pdoc or not 'result' in pdoc['eveapi']: log.error('Invalid XML document / API Error recceived', extra={'data': {'xml': char_doc.body, 'key_id': key_id, 'character_id': character_id}}) return corp = EVEPlayerCharacter.objects.get(id=character_id).corporation charlist = [] for character in pdoc['eveapi']['result']['members']: charlist.append(int(character['characterID'])) charobj, created = EVEPlayerCharacter.objects.get_or_create(id=character['characterID']) if created: charobj.name = character['name'] charobj.corporation = corp charobj.corporation_date = datetime.strptime(character['startDateTime'], "%Y-%m-%d %H:%M:%S").replace(tzinfo=utc) if 'logonDateTime' in character: charobj.last_login = datetime.strptime(character['logonDateTime'], "%Y-%m-%d %H:%M:%S").replace(tzinfo=utc) charobj.last_logoff = datetime.strptime(character['logoffDateTime'], "%Y-%m-%d %H:%M:%S").replace(tzinfo=utc) charobj.current_location_id = int(character['locationID']) else: charobj.last_login = None charobj.last_logoff = None charobj.current_location_id = None charobj.save() if created: import_eve_character.delay(character['characterID']) leftlist = set(corp.eveplayercharacter_set.all().values_list('id', flat=True)) - set(charlist) for id in leftlist: import_eve_character.delay(id)
def process_view(self, request, view_func, view_args, view_kwargs): # CONTRACT: At the end of this, if the user is authenticated, # request.current_book _must_ be populated with a valid book, and # request.books _must_ be a list of Books with length greater than 0. request.current_book = None if hasattr(request, 'user'): if request.user.is_authenticated(): request.books = Book.objects.filter_for_user(request.user) request.current_book = None if request.books: if 'book' in view_kwargs: current_book = request.books.filter( pk=view_kwargs['book'])[0] if current_book: request.current_book = current_book else: return Http404 else: request.current_book = request.books[0] else: sentry.error("No book found for user", exc_info=True, extra={"user": request.user}) request.current_book = Book.objects.create_for_user( request.user) request.books = Book.objects.filter_for_user(request.user) if (gargoyle.is_active('enable_payments', request) and request.current_book): request.can_invite = ( request.current_book.plan and not request.current_book.plan.startswith('basic')) else: request.can_invite = True
def wrapped(request, *args, **kwargs): if not gargoyle.is_active(key, request): if not redirect_to: raise Http404('Switch \'%s\' is not active' % key) else: return redirect(redirect_to) return func(request, *args, **kwargs)
def get_send_url(self, sms_request, account_dict): # Get correct url to use if 'endpoint' in account_dict: endpoint = account_dict['endpoint'] else: url = 'secondary' if gargoyle.is_active('smsgateway-kpn-use-secondary-url') else 'primary' endpoint = settings.SMSGATEWAY_KPNBE_URLS[url] + account_dict['username'] # Encode message msg = sms_request.msg msg = msg.replace(u'€', u'EUR') try: msg = msg.encode('iso-8859-1', 'replace') except: pass querystring = urlencode({ 'username': account_dict['username'], 'password': account_dict['password'], 'mobile_no': ','.join([x[1:] for x in sms_request.to]), 'origin_addr': account_dict.get('signature', '8210'), 'msg': msg, 'msgtype': 'ISO-8859-1' }) return '{}?{}'.format(endpoint, querystring)
def table(request, tableid=None): if request.method == 'POST': return handle_table_post(request, tableid) # Otherwise, it's a GET wwg = WordwallsGame() if tableid: # Check if the user is allowed to enter this table. permitted = wwg.allow_access(request.user, tableid) if gargoyle.is_active('disable_games', request): permitted = False if not permitted: return render(request, 'wordwalls/notPermitted.html', {'tablenum': tableid}) params = wwg.get_add_params(tableid) # Add styling params from user's profile (for styling table # tiles, backgrounds, etc) profile = request.user.aerolithprofile style = profile.customWordwallsStyle if style != "": params['style'] = style meta_info = get_create_meta_info() usermeta = get_user_meta_info(request.user) wgm = None if tableid: wgm = wwg.get_wgm(tableid, False) return render( request, 'wordwalls/table.html', { 'tablenum': tableid if tableid else 0, 'current_host': wgm.host.username if wgm else '', 'multiplayer': (json.dumps(wgm.playerType == WordwallsGameModel. MULTIPLAYER_GAME if wgm else False)), 'user': json.dumps(usermeta), 'addParams': json.dumps(params), 'avatarUrl': profile.avatarUrl, 'lexicon': wgm.lexicon.lexiconName if wgm else None, 'default_lexicon': profile.defaultLexicon.pk, 'challenge_info': json.dumps(meta_info['challenge_info']), 'available_lexica': json.dumps(meta_info['lexica']), 'intercom_app_id': settings.INTERCOM_APP_ID, # Use the webpack server if DEBUG is on. XXX This might not actually # be a good test; consider using an IS_PRODUCTION flag. 'STATIC_SRV': (settings.WEBPACK_DEV_SERVER_URL if (settings.USE_WEBPACK_DEV_SERVER and settings.DEBUG) else '') })
def device_help(request): if gargoyle.is_active('CAN_VIEW_SUPPORT_PHONE', request.user): support_phone = settings.SUPPORT_PHONE else: support_phone = '' context = RequestContext(request, {'support_phone': support_phone}) return render_to_response('device/device-help.html', context)
def _should_add_invalidation_link(email): account = Account.objects.get_by_email(email) if gargoyle.is_active('ALLOW_UNVERIFIED', account): emails = EmailAddress.objects.filter(email=email) result = (emails.count() == 0 or emails.filter(status=EmailStatus.NEW).count() > 0) return result return False
def test_global(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = gargoyle['test'] self.assertTrue(gargoyle.is_active('test')) self.assertTrue(gargoyle.is_active('test', self.user)) switch.status = GLOBAL switch.save() self.assertTrue(gargoyle.is_active('test')) self.assertTrue(gargoyle.is_active('test', self.user))
def is_active(request, switch): """ filter to use gargoyle switches in normal ifs: {% if request|is_active:"switchname" and not user.is_anonymous %} <my>html</my> {% endif %} """ return gargoyle.is_active(switch, request)
def wrapped(request, *args, **kwargs): if not gargoyle.is_active(key, request): if not redirect_to: raise Http404('Switch \'%s\' is not active' % key) elif redirect_to.startswith('/'): return HttpResponseRedirect(redirect_to) else: return HttpResponseRedirect(reverse(redirect_to)) return func(request, *args, **kwargs)
def index_gargoyle(request): """ Example of usage Gargoyle feature flags """ context = {"title": "Regular title"} if gargoyle.is_active(FRONTEND_TITLE_FEATURE, request): context.update({"title": "Fancy title enabled by feature flag"}) return render(request, "playground/index_gargoyle.html", context)
def render(self, context): instances = [i.resolve(context) for i in self.instances] if 'request' in context: instances.append(context['request']) if not gargoyle.is_active(self.name, *instances): return self.nodelist_false.render(context) return self.nodelist_true.render(context)
def clean_api_key(self): if not gargoyle.is_active('eve-cak') and not len(self.cleaned_data['api_key']) == 64: raise forms.ValidationError("Provided API Key is not 64 characters long.") if re.search(r'[^\.a-zA-Z0-9]', self.cleaned_data['api_key']): raise forms.ValidationError("Provided API Key has invalid characters.") return self.cleaned_data['api_key']
def dispatch(self, request, *args, **kwargs): book = None if request.user.is_authenticated(): if hasattr(request, 'current_book'): book = request.current_book if gargoyle.is_active('enable_payments', request): if book and not book.is_paid(): messages.error(request, "Your book is currently unpaid. Please select a subscription, or contact [email protected]") return HttpResponseRedirect('/pricing') return super(BookOwnerMixin, self).dispatch(request, *args, **kwargs)
def delete(self, request, *args, **kwargs): self.object = self.get_object() keyid = self.object.pk if not gargoyle.is_active('eve-softkeydelete', request): self.object.delete() else: self.object.user = None self.object.save() messages.success(self.request, 'EVE API key %s successfully deleted.' % keyid, fail_silently=True) return HttpResponseRedirect(self.get_success_url())
def tikibar_feature_flag_enabled(request): try: from gargoyle import gargoyle return gargoyle.is_active(settings.TIKIBAR, request) except ImportError: if hasattr(settings, 'ENABLE_TIKIBAR'): return settings.ENABLE_TIKIBAR if settings.DEBUG: return settings.DEBUG return False
def render(self, context): if 'request' in context: conditions = [context['request']] else: conditions = [] if not gargoyle.is_active(self.name, *conditions): return self.nodelist_false.render(context) return self.nodelist_true.render(context)
def test_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' # we need a better API for this (model dict isnt cutting it) switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = gargoyle['test'] switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) user = User(pk=5) self.assertTrue(gargoyle.is_active('test', user)) user = User(pk=8771) self.assertFalse(gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_staff', condition='1', ) user = User(pk=8771, is_staff=True) self.assertTrue(gargoyle.is_active('test', user)) user = User(pk=8771, is_superuser=True) self.assertFalse(gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_superuser', condition='1', ) user = User(pk=8771, is_superuser=True) self.assertTrue(gargoyle.is_active('test', user))
def director_api_keys(self): if gargoyle.is_active("eve-cak"): return self.directors.filter( eveaccount__isnull=False, eveaccount__api_keytype__in=[API_KEYTYPE_CORPORATION, API_KEYTYPE_FULL], eveaccount__api_status=API_STATUS_OK, ) else: return self.directors.filter( eveaccount__isnull=False, eveaccount__api_keytype=API_KEYTYPE_FULL, eveaccount__api_status=API_STATUS_OK )
def start_game(request, id): if gargoyle.is_active('disable_games', request): return response( {'serverMsg': _( 'The Aerolith server is currently undergoing ' 'maintenance. Please try again in a few minutes.')}) wwg = WordwallsGame() quiz_params = wwg.start_quiz(id, request.user) if 'error' in quiz_params: return response(quiz_params, StatusCode.BAD_REQUEST) return response(quiz_params)
def __init__(self, *args, **kwargs): super(EveAPIForm, self).__init__(*args, **kwargs) instance = getattr(self, 'instance', None) if instance and instance.pk: # We're editing a existing instance, readonly the userid self.fields['api_user_id'].widget.attrs['readonly'] = True if gargoyle.is_active('eve-cak'): self.fields['api_user_id'].label = 'Key ID' self.fields['api_key'].label = 'Verification Code'
def test_anonymous_user(self): condition_set = 'gargoyle.builtins.UserConditionSet(auth.user)' switch = Switch.objects.create(key='test') switch = gargoyle['test'] switch.status = SELECTIVE switch.save() user = AnonymousUser() self.assertTrue(gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertFalse(gargoyle.is_active('test', user)) switch.clear_conditions(condition_set=condition_set) self.assertTrue(gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='is_anonymous', condition='1', ) self.assertTrue(gargoyle.is_active('test', user)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='1-10', ) self.assertTrue(gargoyle.is_active('test', user))
def start_game(request, id): if gargoyle.is_active('disable_games', request): return response( {'serverMsg': 'Unable to start game as this is temporarily ' 'disabled. Please try again in a few minutes.'}) wwg = WordwallsGame() gameReady = wwg.startRequest(request.user, id) if not gameReady: return response({"serverMsg": request.user.username}) else: quizParams = wwg.startQuiz(id, request.user) return response(quizParams)
def dispatch(self, request, *args, **kwargs): if not self.gargoyle_switch: raise ImproperlyConfigured( 'SwitchActiveMixin requires gargoyle_switch setting') if not gargoyle.is_active(self.gargoyle_switch, request): if not self.gargoyle_redirect_to: raise Http404('Switch \'%s\' is not active' % self.gargoyle_switch) elif self.gargoyle_redirect_to.startswith('/'): return HttpResponseRedirect(self.gargoyle_redirect_to) else: return HttpResponseRedirect(reverse(self.gargoyle_redirect_to)) return super(SwitchActiveMixin, self).dispatch(request, *args, **kwargs)
def test_ip_address(self): condition_set = "gargoyle.builtins.IPAddressConditionSet" switch = Switch.objects.create(key="test", status=SELECTIVE) switch = gargoyle["test"] request = HttpRequest() request.META["REMOTE_ADDR"] = "192.168.1.1" self.assertTrue(gargoyle.is_active("test", request)) switch.add_condition(condition_set=condition_set, field_name="ip_address", condition="192.168.1.1") self.assertTrue(gargoyle.is_active("test", request)) switch.clear_conditions(condition_set=condition_set) switch.add_condition(condition_set=condition_set, field_name="ip_address", condition="127.0.0.1") self.assertFalse(gargoyle.is_active("test", request)) switch.clear_conditions(condition_set=condition_set) self.assertTrue(gargoyle.is_active("test", request)) switch.add_condition(condition_set=condition_set, field_name="percent", condition="50-100") self.assertTrue(gargoyle.is_active("test", request)) switch.clear_conditions(condition_set=condition_set) switch.add_condition(condition_set=condition_set, field_name="percent", condition="0-50") self.assertFalse(gargoyle.is_active("test", request))
def setup_smtp_settings(): # Check for multiple mail hosts hosts = getattr(settings, 'EMAIL_HOSTS', None) if hosts is not None: from gargoyle import gargoyle for host, config in hosts.items(): if gargoyle.is_active('mailer-%s' % host): settings.EMAIL_HOST = config['host'] settings.EMAIL_USE_TLS = config['use_tls'] settings.EMAIL_PORT = config['port'] settings.EMAIL_HOST_USER = config['user'] settings.EMAIL_HOST_PASSWORD = config['password'] break
def eveapi_del(request, userid, post_save_redirect='/'): """ Delete a EVE API key from a account """ if gargoyle.is_active('eve-keydelete', request): try: acc = EVEAccount.objects.get(pk=userid) except EVEAccount.DoesNotExist: return redirect(post_save_redirect) if acc.user == request.user: acc.delete() messages.success(request, "EVE API key successfully deleted.", fail_silently=True) return redirect(post_save_redirect)
def dispatch(self, request, *args, **kwargs): if not gargoyle.is_active('import_from_google', request): return HttpResponseRedirect('/') app = SocialApp.objects.filter(provider='google')[0] url = "{}?process=connect&next={}".format( reverse("google_login"), reverse("import-google-contacts", kwargs={'book': self.request.current_book.id}), ) try: token = SocialToken.objects.get(account__user=self.request.user, app=app) except SocialToken.DoesNotExist: sentry.error("Social token missing in google import", extra={ "user": self.request.user, }) return HttpResponseRedirect(url) try: creds = GoogleCredentials( access_token=token.token, token_expiry=None, token_uri=GOOGLE_TOKEN_URI, client_id=app.client_id, client_secret=app.secret, refresh_token=None, user_agent='Python', revoke_uri=None, ) http = httplib2.Http() http = creds.authorize(http) people_service = build(serviceName='people', version='v1', http=http) connections = people_service.people().connections().list( resourceName='people/me', pageSize=50).execute() except HttpAccessTokenRefreshError: return HttpResponseRedirect(url) cache.set("{}::google-import".format(request.user.username), "processing", 86400) Channel('import-google-contacts').send({ 'user_id': self.request.user.id, 'book_id': self.request.current_book.id }) messages.success( request, "We're importing your Google contacts now! You'll receive an email when we're done." ) return HttpResponseRedirect('/')
def checked(self): # If the akismet_filtering setting is enabled, the queryset should be # further filtered to exclude any messages which have not been checked # for spam yet. qs = self._clone(setup=True) try: from gargoyle import gargoyle except ImportError: pass else: if gargoyle.is_active('akismet_filtering'): qs = qs.filter(spam_status__isnull=False) return qs
def start_game(request, id): if gargoyle.is_active('disable_games', request): return response({ 'serverMsg': 'Unable to start game as this is temporarily ' 'disabled. Please try again in a few minutes.' }) wwg = WordwallsGame() gameReady = wwg.startRequest(request.user, id) if not gameReady: return response({"serverMsg": request.user.username}) else: quizParams = wwg.startQuiz(id, request.user) return response(quizParams)
def form_valid(self, form): form.instance.sender = self.request.user if form.cleaned_data.get('share_book'): book = BookOwner.objects.get(user=self.request.user, ).book if gargoyle.is_active('enable_payments', self.request): invitations = Invitation.objects.filter(book=book) if book.plan and len(invitations) >= payment_constants.PLANS[ book.plan]['collaborators']: form.add_error( field=None, error="You don't have any invites left on this plan.") return self.form_invalid(form) form.instance.book = book messages.success( self.request, "Invited {}".format(form.cleaned_data.get('email')), ) return super(CreateInviteView, self).form_valid(form)
def get_context_data(self, *args, **kwargs): context = super(CreateInviteView, self).get_context_data(*args, **kwargs) if self.request.current_book: book = self.request.current_book else: book = BookOwner.objects.get(user=self.request.user).book invitations = Invitation.objects.filter(book=book) if gargoyle.is_active('enable_payments', self.request): has_more_invites = ( book.plan and len(invitations) < payment_constants.PLANS[book.plan]['collaborators']) if not has_more_invites: messages.warning( self.request, "You are out of invites for this book. You can still invite people to ContactOtter, but need to upgrade your plan to share this book with other collaborators." ) context['invitations'] = invitations
def test_ip_address(self): condition_set = 'gargoyle.builtins.IPAddressConditionSet' switch = Switch.objects.create( key='test', status=SELECTIVE, ) switch = gargoyle['test'] request = HttpRequest() request.META['REMOTE_ADDR'] = '192.168.1.1' self.assertTrue(gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='192.168.1.1', ) self.assertTrue(gargoyle.is_active('test', request)) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='ip_address', condition='127.0.0.1', ) self.assertFalse(gargoyle.is_active('test', request)) switch.clear_conditions(condition_set=condition_set) self.assertTrue(gargoyle.is_active('test', request)) switch.add_condition( condition_set=condition_set, field_name='percent', condition='50-100', ) self.assertTrue(gargoyle.is_active('test', request)) switch.clear_conditions(condition_set=condition_set) switch.add_condition( condition_set=condition_set, field_name='percent', condition='0-50', ) self.assertFalse(gargoyle.is_active('test', request))
def dispatch(self, request, *args, **kwargs): # TODO: Make this work even when the user isn't logged in if not gargoyle.is_active('enable_payments', request): return HttpResponseRedirect('/pricing') self.plan = request.GET.get('plan') plan = payment_constants.PLANS[self.plan] if not self.plan or not plan['is_active']: messages.warning(self.request, "Please select a plan") url = reverse("pricing") return HttpResponseRedirect(url) if not self.request.user.is_authenticated(): url = "{}?next=/pay/%3Fplan%3D{}".format(reverse("account_signup"), self.plan) return HttpResponseRedirect(url) try: if self.request.user.is_authenticated(): self.book = Book.objects.get_for_user(user=self.request.user) except Book.DoesNotExist: self.book = None return super(PaymentView, self).dispatch(request, *args, **kwargs)
def tikibar_feature_flag_enabled(request): try: args = (request, ) admin_cookie = request.COOKIES.get('admin_user') if admin_cookie: import urlparse from ebapps.ebauth import superuser from ebapps.ebauth.models import User admin_cookie = urlparse.unquote(admin_cookie) if superuser.validate_admin_switchto_cookie(admin_cookie): parts = superuser.parse_admin_switchto_cookie(admin_cookie) admin_user = User.objects.get(email=parts['email']) args += (admin_user, ) from gargoyle import gargoyle return gargoyle.is_active(settings.TIKIBAR, *args) except (ImportError, exceptions.ObjectDoesNotExist): if hasattr(settings, 'ENABLE_TIKIBAR'): return settings.ENABLE_TIKIBAR if settings.DEBUG: return settings.DEBUG return False
def is_cached_hitcount_enabled(): return gargoyle.is_active('cached_hitcount', default=True) and CACHED_HITCOUNT_ENABLED
def is_active(switch_name): from django.conf import settings from gargoyle import gargoyle switch_enabled = gargoyle.is_active(switch_name) enabled = switch_enabled or settings.TEST_FEEDLY return enabled
def handle(self, *args, **options): logger.info("Starting daily reminder job") now = timezone.now() yesterday = now - timedelta(days=2) last_week = now - timedelta(days=7) last_month = now - timedelta(days=30) last_quarter = now - timedelta(days=90) books_to_check = BookOwner.objects.filter(send_contact_reminders=True) for bookowner in books_to_check: user = bookowner.user if not gargoyle.is_active('scheduled_reminders', user): return book = bookowner.book logger.debug("Starting daily reminders for bookowner", extra={'owner': bookowner}) daily_reminders = Contact.objects.for_user( user=user, book=book).filter( reminder_frequency='daily', last_contact__lte=yesterday, ) weekly_reminders = None monthly_reminders = None quarterly_reminders = None if now.weekday() == bookowner.weekly_reminder_day: weekly_reminders = Contact.objects.for_user( user=user, book=book).filter( reminder_frequency='weekly', last_contact__lte=last_week, ) monthly_reminders = Contact.objects.for_user( user=user, book=book).filter( reminder_frequency='monthly', last_contact__lte=last_month, ) quarterly_reminders = Contact.objects.for_user( user=user, book=book).filter( reminder_frequency='quarterly', last_contact__lte=last_quarter, ) has_high_interval_contacts = weekly_reminders or monthly_reminders or quarterly_reminders has_contacts = has_high_interval_contacts or daily_reminders subject = '[ContactOtter] Daily Contact Reminder' if has_high_interval_contacts: subject = '[ContactOtter] Weekly Contact Reminders' context = { 'daily_contacts': daily_reminders, 'weekly_contacts': weekly_reminders, 'monthly_contacts': monthly_reminders, 'quarterly_contacts': quarterly_reminders, 'book': book, 'has_high_interval_contacts': has_high_interval_contacts } if has_contacts: txt = get_template('email/contact_reminder.txt').render( context) html = get_template('email/contact_reminder.html').render( context) message = EmailMultiAlternatives( subject=subject, body=txt, from_email="ContactOtter <*****@*****.**>", to=[user.email], ) message.attach_alternative(html, "text/html") try: logger.debug("Trying to send daily reminder") message.send() logger.debug("Sent message to {} successfuly".format(user)) except: sentry.error('Problem sending contact reminder', exc_info=True, extra={ 'user': user, 'book': book }) books_to_check = BookOwner.objects.filter(send_birthday_reminders=True) for bookowner in books_to_check: book = bookowner.book user = bookowner.user birthdays = ContactField.objects.filter( Q(label='Birthday') | Q(label='birthday') | Q(label='BIRTHDAY'), kind=contact_constants.FIELD_TYPE_DATE, value=timezone.now().strftime("%Y-%m-%d"), contact__book=book, ) contacts = None if birthdays: contacts = [birthday.contact for birthday in birthdays] if contacts: context = { 'contacts': contacts, 'domain': Site.objects.get_current().domain, } subject = "[ContactOtter] Birthday reminder" txt = get_template('email/birthday_reminder.txt').render( context) html = get_template('email/birthday_reminder.html').render( context) message = EmailMultiAlternatives( subject=subject, body=txt, from_email='ContactOtter <*****@*****.**>', to=[user.email], ) message.attach_alternative(html, "text/html") try: logger.debug( "Trying to send message to {} about {}".format( user, contact)) message.send() logger.debug("Sent message to {} successfuly".format(user)) except: sentry.error('Problem sending birthday reminder', exc_info=True, extra={ 'user': user, 'book': book })
def table(request, id): logger.info("request: %s", request.method) if request.method == 'POST': action = request.POST['action'] logger.info('action %s', action) if action == "start": return start_game(request, id) elif action == "guess": logger.info('%s: guess %s, table %s', request.user.username, request.POST['guess'], id) wwg = WordwallsGame() state = wwg.guess(request.POST['guess'].strip(), id, request.user) return response({'g': state[0], 'C': state[1]}) elif action == "gameEnded": wwg = WordwallsGame() ret = wwg.checkGameEnded(id) # 'going' is the opposite of 'game ended' return response({'g': not ret}) elif action == "giveUp": wwg = WordwallsGame() ret = wwg.giveUp(request.user, id) return response({'g': not ret}) elif action == "save": wwg = WordwallsGame() ret = wwg.save(request.user, id, request.POST['listname']) return response(ret) elif action == "giveUpAndSave": wwg = WordwallsGame() ret = wwg.giveUpAndSave(request.user, id, request.POST['listname']) # this shouldn't return a response, because it's not going to be # caught by the javascript logger.debug("Give up and saving returned: %s" % ret) return response(ret) elif action == "savePrefs": profile = request.user.get_profile() profile.customWordwallsStyle = request.POST['prefs'] profile.save() return response({'success': True}) elif action == "getDcData": wwg = WordwallsGame() dcId = wwg.getDcId(id) if dcId > 0: leaderboardData = getLeaderboardDataDcInstance( DailyChallenge.objects.get(pk=dcId)) return response(leaderboardData) else: # it's a GET wwg = WordwallsGame() permitted = wwg.permit(request.user, id) if gargoyle.is_active('disable_games', request): permitted = False if permitted: params = wwg.getAddParams(id) # Add styling params from user's profile (for styling table # tiles, backgrounds, etc) try: profile = request.user.get_profile() style = profile.customWordwallsStyle if style != "": params['style'] = style except: pass return render( request, 'wordwalls/table.html', { 'tablenum': id, 'username': request.user.username, 'addParams': json.dumps(params), 'avatarUrl': profile.avatarUrl, 'CURRENT_VERSION': CURRENT_VERSION }) else: return render(request, 'wordwalls/notPermitted.html', {'tablenum': id})
def render(self, context): default_flags_dict = getattr(settings, 'GARGOYLE_SWITCH_DEFAULTS', {}) flag_values = {} for flag_key in default_flags_dict: flag_values[flag_key] = gargoyle.is_active(flag_key) return json.dumps(flag_values)
def start_quiz(self, tablenum, user): wgm = self.get_wgm(tablenum) if not wgm: return self.create_error_message(_("That table does not exist.")) state = json.loads(wgm.currentGameState) if state["quizGoing"]: logger.info("The quiz is going, state %s", state) # The quiz is running right now; do not attempt to start again return self.create_error_message( _("The quiz is currently running.")) if gargoyle.is_active("disable_games"): return self.create_error_message( _("Please wait a few minutes. Aerolith is currently " "undergoing maintenance.")) if wgm.is_multiplayer(): if user != wgm.host: return self.create_error_message( _("{user} wants to start the game, but only the host " "{host} can do that.").format(user=user, host=wgm.host)) start_message = "" word_list = wgm.word_list if not word_list: return self.create_error_message( _("It appears this word list has been deleted. Please " "load or create a new word list.")) if word_list.questionIndex > word_list.numCurAlphagrams - 1: start_message += _("Now quizzing on missed list.") + "\r\n" word_list.set_to_missed() state["quizGoing"] = False if word_list.numCurAlphagrams == 0: wgm.currentGameState = json.dumps(state) wgm.save() return self.create_error_message( _("The quiz is done. Please load a new word list!")) cur_questions_obj = json.loads(word_list.curQuestions) idx = word_list.questionIndex num_qs_per_round = state["questionsToPull"] qs = cur_questions_obj[idx:(idx + num_qs_per_round)] start_message += _( "These are questions %(qbegin)s through %(qend)s of " "%(qtotal)s.") % { "qbegin": idx + 1, "qend": len(qs) + idx, "qtotal": word_list.numCurAlphagrams, } word_list.questionIndex += num_qs_per_round qs_set = set(qs) if len(qs_set) != len(qs): logger.error("Question set is not unique!!") orig_questions = json.loads(word_list.origQuestions) questions, answer_hash = self.load_questions(qs, orig_questions, word_list.lexicon) state["quizGoing"] = True # start quiz state["quizStartTime"] = time.time() state["answerHash"] = answer_hash state["originalAnswerHash"] = copy.deepcopy(answer_hash) state["numAnswersThisRound"] = len(answer_hash) state["questions"] = [{ "a": q["a"], "ws": [w["w"] for w in q["ws"]] } for q in questions] wgm.currentGameState = json.dumps(state) wgm.save() # XXX: Autosave doesn't really do anything for saved lists. It # always saves, regardless! Oh well... word_list.save() game_type = state["gameType"] if word_list.category == WordList.CATEGORY_BUILD: game_type += "_build" # This is hell of ghetto. ret = { "questions": questions, "time": state["timerSecs"], "gameType": game_type, "serverMsg": start_message, } return ret
def wrapped(request, *args, **kwargs): if not gargoyle.is_active(key, request): raise Http404('Switch \'%s\' is not active' % key) return func(request, *args, **kwargs)