def token_obj(self): if not hasattr(self, '_token_obj'): self._token_obj, _ = Token.get_or_connect(token=self.identifier.hget()) return self._token_obj
def manage_token(self, *args, **kwargs): from gim.core.limpyd_models import Token Token.update_token_from_gh(self, *args, **kwargs)
def complete_auth(self): # check state attended_state = self.request.session.get('github-auth-state', None) if not attended_state: return False, "Unexpected request, please retry" del self.request.session['github-auth-state'] state = self.request.GET.get('state', None) if state.strip() != attended_state.strip(): return False, "Unexpected request, please retry" # get code code = self.request.GET.get('code', None) if not code: return False, "Authentication denied, please retry" # get the token for the given code try: gh = self.get_github_connection() token = gh.get_access_token(code) except: token = None if not token: return False, "Authentication failed, please retry" # do we have a user for this token ? try: user_with_token = GithubUser.objects.get(token=token) except GithubUser.DoesNotExist: user_with_token = None else: user_with_token.token = None user_with_token.save(update_fields=['token']) # get informations about this user try: user_infos = Connection(access_token=token).user.get() except: user_infos = None if not user_infos: return False, "Cannot get user informations, please retry" # create/update and get a user with the given infos and token try: user = GithubUser.objects.create_or_update_from_dict( data=user_infos, defaults={'simple': {'token': token}}) except: return False, "Cannot save user informations, please retry" # reject banned users if not user.is_active: return False, "This account has been deactivated" # authenticate the user (needed to call login later) user = authenticate(username=user.username, token=user.token) if not user: return False, "Final authentication failed, please retry" # and finally login login(self.request, user) # set its username to the token user.token_object.username.hset(user.username) # remove other tokens for this username from gim.core.limpyd_models import Token for user_token in list(Token.collection(username=user.username).instances()): if user_token.token.hget() != token: user_token.delete() # add a job to fetch available repositories job = FetchAvailableRepositoriesJob.add_job(user.id, inform_user=1) if job.status == STATUSES.DELAYED: return True, "Authentication successful, welcome back!" else: return True, "Authentication successful, we are currently fetching repositories you can subscribe to (ones you own, collaborate to, or in your organizations)"
def _get_gh(self): """ Return a Connection object based on arguments saved in the job, or by type of permission, to get one from the Token model """ from gim.core.limpyd_models import Token args = self.gh_args.hgetall() if "access_token" not in args: args = None permission = getattr(self, "permission", "read") token = None # we have connection args: get the token if available if args: try: token_kwargs = {"token": args["access_token"]} # ignore the available flag for "self" if permission != "self": token_kwargs["available"] = 1 try: token = Token.get(**token_kwargs) except IndexError: # changed during the "get"... retry once # explanation: the get first check the length of the result # and if it's 1, then it retrieves the first, but in the # meantime, the data may have changed and there is result # anymore... token = Token.get(**token_kwargs) except: raise except (Token.DoesNotExist, KeyError): pass else: # final check on remaining api calls if int(token.rate_limit_remaining.get() or 0): return token.gh # no token, try to get one... repository = None if permission == "self": # forced to use the current one, but not available... pass else: # if we have a repository, get one following permission repository = getattr(self, "repository") if repository: if repository.private and permission not in ("admin", "push", "pull"): # force correct permission if repository is private permission = "pull" token = Token.get_one_for_repository(repository.pk, permission) # no repository, not "self", but want one ? don't know why but ok... else: token = Token.get_one() # if we don't have token it's that there is no one available: we delay # the job if not token: self.status.hset(STATUSES.DELAYED) if hasattr(self, "delay_for_gh"): # use the "delay_for_gh" attribute if any to delay the job for X seconds self.delayed_until.hset(compute_delayed_until(delayed_for=self.delay_for_gh)) else: # check the first available gh if permission == "self": if args: try: token = Token.get(token=args["access_token"]) except Token.DoesNotExist: token = Token.get(username=args["username"]) elif repository: token = Token.get_one_for_repository( repository.pk, permission, available=False, sort_by="rate_limit_reset" ) else: token = Token.get_one(available=False, sort_by="rate_limit_reset") # if we have a token, get it's delay before availability, and # set it on the job for future use if token: remaining = token.get_remaining_seconds() if remaining is not None and remaining >= 0: self.delayed_until.hset(compute_delayed_until(remaining)) else: self.delayed_until.delete() self.gh = token.gh else: # no token at all ? we may have no one for this permission ! # so retry in 15mn self.delayed_until.hset(compute_delayed_until(delayed_for=60 * 15)) return None # save it in the job, useful when cloning to avoid searching for a new # gh (will only happen if it is not available anymore) self.gh = token.gh # and ok, return it return token.gh