def external_login(request): goto = request.GET.get("redirect") if not goto: return render(request, "error.html", {"message": "Нужен параметр ?redirect"}) me = authorized_user(request) if not me: redirect_here_again = quote(reverse("external_login") + f"?redirect={goto}", safe="") return redirect(reverse("login") + f"?goto={redirect_here_again}") # TODO: it would be nice to show "authorize" window here payload = { "user_slug": me.slug, "user_name": me.full_name, "user_email": me.email, "exp": datetime.utcnow() + settings.JWT_EXP_TIMEDELTA, } jwt_token = jwt.encode(payload, settings.JWT_PRIVATE_KEY, settings.JWT_ALGORITHM).decode("utf-8") # TODO: implement proper url parsing + domain validation + query building if "?" in goto: goto += f"&jwt={jwt_token}" else: goto += f"?jwt={jwt_token}" return redirect(goto)
def external_login(request): goto = request.GET.get("redirect") if not goto: return render(request, "error.html", {"message": "Нужен параметр ?redirect"}, status=400) # check if user is logged in or redirect to login screen me = authorized_user(request) if not me: redirect_here_again = quote(reverse("external_login") + f"?redirect={goto}", safe="") return redirect(reverse("login") + f"?goto={redirect_here_again}") # we only authorize applications we know with the keys we set for them app_id = request.GET.get("app_id") app = Apps.objects.filter(id=app_id).first() if not app: return render( request, "error.html", {"message": "Неизвестное приложение, проверьте параметр ?app_id"}, status=400) # check if redirect_url is in the list of allowed urls goto_parsed = urlparse(goto) goto_path_without_params = f"{goto_parsed.scheme}://{goto_parsed.netloc}{goto_parsed.path}" if goto_path_without_params not in app.redirect_urls: return render( request, "error.html", { "message": f"'{goto}' не находится в списке разрешеных redirect_urls для этого приложения" }, status=400) # TODO: show "authorize" window and ask for user's consent here # success! issue a new signed JWT payload = { "user_slug": me.slug, "user_name": me.full_name, "user_email": me.email, "exp": datetime.utcnow() + timedelta(hours=app.jwt_expire_hours), } jwt_token = jwt.encode(payload, app.jwt_secret, algorithm=app.jwt_algorithm) # add ?jwt= to redirect_url and activate the redirect goto_params = parse_qsl(goto_parsed.query) goto_params += [("jwt", jwt_token)] return redirect(f"{goto_path_without_params}?{urlencode(goto_params)}")
def board(request, board_slug): board = get_object_or_404(Board, slug=board_slug) if board.is_private: me = authorized_user(request) if not me: return render(request, "board_no_access.html", { "board": board }, status=401) blocks = BoardBlock.objects.filter(board=board) feeds = BoardFeed.objects.filter(board=board) return render(request, "board.html", { "board": board, "blocks": blocks, "feeds": feeds, })
def external(request): goto = request.GET.get("redirect") if not goto: return render(request, "error.html", {"message": "Нужен параметр ?redirect"}) me = authorized_user(request) if not me: redirect_here_again = quote(reverse("external") + f"?redirect={goto}", safe="") return redirect(reverse("login") + f"?goto={redirect_here_again}") payload = { "user_id": me.id, "user_name": me.name, "exp": datetime.utcnow() + settings.JWT_EXP_TIMEDELTA, } jwt_token = jwt.encode(payload, settings.JWT_SECRET, settings.JWT_ALGORITHM).decode("utf-8") return redirect(f"{goto}?jwt={jwt_token}")
def patreon_login(request): user = authorized_user(request) if user: return redirect("profile", user.slug) state = {} goto = request.GET.get("goto") if goto: state["goto"] = goto query_string = urlencode({ "response_type": "code", "client_id": settings.PATREON_CLIENT_ID, "redirect_uri": settings.PATREON_REDIRECT_URL, "scope": settings.PATREON_SCOPE, "state": urlencode(state) if state else "", }) return redirect(f"{settings.PATREON_AUTH_URL}?{query_string}")
def board(request, board_slug): board = get_object_or_404(Board, slug=board_slug) if board.is_private: me = authorized_user(request) if not me: return render(request, "board_no_access.html", { "board": board }, status=401) cached_page = cache.get(f"board_{board.slug}") if cached_page and board.refreshed_at <= datetime.utcnow() - timedelta(seconds=settings.BOARD_CACHE_SECONDS): return cached_page blocks = BoardBlock.objects.filter(board=board) feeds = BoardFeed.objects.filter(board=board) result = render(request, "board.html", { "board": board, "blocks": blocks, "feeds": feeds, }) cache.set(f"board_{board.slug}", result, settings.BOARD_CACHE_SECONDS) return result
def me(request): return {"me": authorized_user(request)}