{"id":30697,"date":"2023-07-16T11:45:22","date_gmt":"2023-07-16T08:15:22","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/"},"modified":"2023-07-16T11:45:22","modified_gmt":"2023-07-16T08:15:22","slug":"impersonation-feature-using-rails-and-react-nextjs-58g5","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/","title":{"rendered":"\u0648\u06cc\u0698\u06af\u06cc \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 Rails \u0648 NextJS"},"content":{"rendered":"<div data-article-id=\"1538416\" id=\"article-body\">\n<p>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u0628\u0647 \u0634\u0645\u0627 \u0646\u0634\u0627\u0646 \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f <strong>\u0628\u0647 \u0627\u062f\u0645\u06cc\u0646 \u0647\u0627\u06cc \u062f\u0627\u062e\u0644\u06cc \u062e\u0648\u062f \u0627\u062c\u0627\u0632\u0647 \u062f\u0647\u06cc\u062f \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u06cc\u06a9 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u062c\u0639\u0644 \u06a9\u0646\u0646\u062f<\/strong>.  \ud83e\udd77<\/p>\n<p>\u0627\u06cc\u0646 \u06cc\u06a9 \u0648\u06cc\u0698\u06af\u06cc \u0641\u0648\u0642\u200c\u0627\u0644\u0639\u0627\u062f\u0647 \u0627\u0631\u0632\u0634\u0645\u0646\u062f \u0627\u0633\u062a \u06a9\u0647 \u0627\u06a9\u062b\u0631 \u0634\u0631\u06a9\u062a\u200c\u0647\u0627\u06cc SaaS \u0628\u0631\u0627\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0628\u0647\u062a\u0631 \u0627\u0632 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u200c\u0647\u0627\u06cc \u0645\u0634\u062a\u0631\u06cc\u060c \u0628\u0627 \u0622\u0646 \u062d\u0633\u0627\u0628 \u0645\u06cc\u200c\u06a9\u0646\u0646\u062f.  \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0628\u0647 \u0627\u062f\u0645\u06cc\u0646 \u0647\u0627 \u0627\u062c\u0627\u0632\u0647 \u0645\u06cc \u062f\u0647\u062f \u0622\u0646\u0686\u0647 \u0631\u0627 \u06a9\u0647 \u0645\u0634\u062a\u0631\u06cc \u0645\u06cc \u0628\u06cc\u0646\u062f \u0628\u0628\u06cc\u0646\u0646\u062f \u0648 \u0628\u0647 \u0622\u0646\u0647\u0627 \u06a9\u0645\u06a9 \u06a9\u0646\u0646\u062f.  \u0628\u0631\u0627\u06cc \u0627\u0633\u062a\u0627\u0631\u062a\u200c\u0622\u067e\u200c\u0647\u0627\u06cc \u062f\u0631 \u0645\u0631\u0627\u062d\u0644 \u0627\u0648\u0644\u06cc\u0647\u060c \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0627\u0647\u0645\u06cc\u062a \u0628\u06cc\u0634\u062a\u0631\u06cc \u062f\u0627\u0631\u062f \u0632\u06cc\u0631\u0627 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u062a\u0648\u0633\u0639\u0647 \u0642\u0627\u0628\u0644\u06cc\u062a\u200c\u0647\u0627\u06cc \u0648\u06cc\u0631\u0627\u06cc\u0634\u06cc \u0645\u062a\u0639\u062f\u062f \u0645\u062f\u06cc\u0631\u06cc\u062a \u0631\u0627 \u0641\u0642\u0637 \u0628\u0631\u0627\u06cc \u062a\u06a9\u0631\u0627\u0631 \u0639\u0645\u0644\u06a9\u0631\u062f\u0647\u0627\u06cc \u0627\u0648\u0644\u06cc\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0627\u0632 \u0628\u06cc\u0646 \u0645\u06cc\u200c\u0628\u0631\u062f.  \u0639\u0644\u0627\u0648\u0647 \u0628\u0631 \u0627\u06cc\u0646\u060c \u0628\u0627 \u062a\u0648\u062c\u0647 \u0628\u0647 \u062f\u0631\u06a9 \u0631\u0648\u0634\u0646\u06cc \u0627\u0632 \u0645\u0639\u0645\u0627\u0631\u06cc \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632\u060c \u06a9\u0647 \u062f\u0631 \u0627\u06cc\u0646 \u067e\u0633\u062a \u0648\u0628\u0644\u0627\u06af \u0628\u0647 \u0628\u0631\u0631\u0633\u06cc \u0622\u0646 \u0645\u06cc\u200c\u067e\u0631\u062f\u0627\u0632\u06cc\u0645\u060c \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0631\u0627 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646 \u062f\u0631 \u06cc\u06a9 \u0631\u0648\u0632 \u06a9\u0627\u0631\u06cc \u0627\u0646\u062c\u0627\u0645 \u062f\u0627\u062f.  \ud83d\ude18<\/p>\n<p>\u0645\u0639\u06cc\u0627\u0631\u0647\u0627\u06cc \u067e\u0630\u06cc\u0631\u0634 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u0647 \u0634\u0631\u062d \u0632\u06cc\u0631 \u0628\u0627\u0634\u062f:<\/p>\n<blockquote>\n<p>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u06a9\u0627\u0631\u0628\u0631 \u0645\u062f\u06cc\u0631\u060c \u0628\u0627\u06cc\u062f \u0628\u062a\u0648\u0627\u0646\u0645 \u0628\u0647 \u062f\u06a9\u0645\u0647 &#8220;\u062c\u0639\u0644 \u0647\u0648\u06cc\u062a&#8221; \u062f\u0631 \u0646\u0645\u0627\u06cc\u0647 \u06a9\u0627\u0631\u0628\u0631 \u062f\u0633\u062a\u0631\u0633\u06cc \u062f\u0627\u0634\u062a\u0647 \u0628\u0627\u0634\u0645.  \u0648\u0642\u062a\u06cc \u0631\u0648\u06cc \u0627\u06cc\u0646 \u062f\u06a9\u0645\u0647 \u06a9\u0644\u06cc\u06a9 \u0645\u06cc\u200c\u06a9\u0646\u0645\u060c \u0628\u0627\u06cc\u062f \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u062a\u0628 \u062c\u062f\u06cc\u062f \u0628\u0627\u0632 \u06a9\u0646\u062f\u060c \u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u0646 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631 \u0627\u0646\u062a\u062e\u0627\u0628\u06cc \u0648\u0627\u0631\u062f \u0634\u062f\u0647\u200c\u0627\u0645 \u0648 \u0628\u0647 \u0645\u0646 \u0627\u062c\u0627\u0632\u0647 \u0645\u06cc\u200c\u062f\u0647\u062f \u0627\u0632 \u0637\u0631\u0641 \u0627\u0648 \u0639\u0645\u0644 \u06a9\u0646\u0645.  \u0628\u0647 \u062f\u0644\u0627\u06cc\u0644 \u0627\u0645\u0646\u06cc\u062a\u06cc\u060c \u062c\u0644\u0633\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0628\u0627\u06cc\u062f 20 \u062f\u0642\u06cc\u0642\u0647 \u0637\u0648\u0644 \u0628\u06a9\u0634\u062f \u06a9\u0647 \u062f\u0631 \u0645\u0642\u0627\u06cc\u0633\u0647 \u0628\u0627 \u062c\u0644\u0633\u0627\u062a \u0648\u0631\u0648\u062f \u0628\u0647 \u0633\u06cc\u0633\u062a\u0645 \u0645\u0639\u0645\u0648\u0644\u06cc \u06a9\u0648\u062a\u0627\u0647\u200c\u062a\u0631 \u0627\u0633\u062a \u0648 \u0645\u0639\u0645\u0648\u0644\u0627\u064b \u062a\u0645\u0627\u0645 \u0686\u06cc\u0632\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0645\u0646 \u0646\u06cc\u0627\u0632 \u062f\u0627\u0631\u0645.<\/p>\n<\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/07\/\u0648\u06cc\u0698\u06af\u06cc-\u062c\u0639\u0644-\u0647\u0648\u06cc\u062a-\u0628\u0627-\u0627\u0633\u062a\u0641\u0627\u062f\u0647-\u0627\u0632-Rails-\u0648-NextJS.png\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"524\" title=\"\"><\/p>\n<hr\/>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C_%D8%B3%D8%B7%D8%AD_%D8%A8%D8%A7%D9%84%D8%A7\" >\u0645\u0639\u0645\u0627\u0631\u06cc \u0633\u0637\u062d \u0628\u0627\u0644\u0627:<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B1%D8%AD%D9%84%D9%87_1_%D9%85%D8%AF%D9%84_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\" >\u0645\u0631\u062d\u0644\u0647 1: \u0645\u062f\u0644 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B1%D8%AD%D9%84%D9%87_2_%D8%AF%DA%A9%D9%85%D9%87_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\" >\u0645\u0631\u062d\u0644\u0647 2: \u062f\u06a9\u0645\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B1%D8%AD%D9%84%D9%87_3_%D9%85%D8%B3%DB%8C%D8%B1_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA_Frontend\" >\u0645\u0631\u062d\u0644\u0647 3: \u0645\u0633\u06cc\u0631 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a Frontend<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B1%D8%AD%D9%84%D9%87_4_%D9%86%D9%82%D8%B7%D9%87_%D9%BE%D8%A7%DB%8C%D8%A7%D9%86%DB%8C_Backend_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%AA%D8%A8%D8%A7%D8%AF%D9%84_%D9%86%D8%B4%D8%A7%D9%86%D9%87_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\" >\u0645\u0631\u062d\u0644\u0647 4: \u0646\u0642\u0637\u0647 \u067e\u0627\u06cc\u0627\u0646\u06cc Backend \u0628\u0631\u0627\u06cc \u062a\u0628\u0627\u062f\u0644 \u0646\u0634\u0627\u0646\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%85%D8%B1%D8%AD%D9%84%D9%87_5_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7\" >\u0645\u0631\u062d\u0644\u0647 5: \u062a\u0633\u062a \u0647\u0627!<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/impersonation-feature-using-rails-and-react-nextjs-58g5\/#%D9%BE%D8%A7%D8%AF%D8%A7%D8%B4_%DA%A9%D8%A7%D8%B1%DA%AF%D8%B1_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%BE%D8%A7%DA%A9_%DA%A9%D8%B1%D8%AF%D9%86_%D8%B3%D9%88%D8%A7%D8%A8%D9%82_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA_%D9%82%D8%AF%DB%8C%D9%85%DB%8C\" >\u067e\u0627\u062f\u0627\u0634: \u06a9\u0627\u0631\u06af\u0631 \u0628\u0631\u0627\u06cc \u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0633\u0648\u0627\u0628\u0642 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0642\u062f\u06cc\u0645\u06cc<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C_%D8%B3%D8%B7%D8%AD_%D8%A8%D8%A7%D9%84%D8%A7\"><\/span>\n<p>  \u0645\u0639\u0645\u0627\u0631\u06cc \u0633\u0637\u062d \u0628\u0627\u0644\u0627:<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0645\u0646 \u0627\u0628\u062a\u062f\u0627 \u0645\u0639\u0645\u0627\u0631\u06cc \u06a9\u0644\u06cc \u0631\u0627 \u0634\u0631\u062d \u0645\u06cc \u062f\u0647\u0645\u060c \u06a9\u0647 \u0627\u0645\u06cc\u062f\u0648\u0627\u0631\u06cc\u0645 \u0628\u062a\u0648\u0627\u0646\u062f \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0647\u0627\u0645 \u0628\u062e\u0634 \u0628\u0631\u0627\u06cc \u0633\u0627\u062e\u062a \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u062f\u0631 \u0647\u0631 \u0686\u0627\u0631\u0686\u0648\u0628\u06cc \u0628\u0627\u0634\u062f.<\/p>\n<p><strong>\u0627\u06cc\u0646 \u0631\u0627\u0647 \u062d\u0644 \u0628\u0631\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645\u06cc \u0637\u0631\u0627\u062d\u06cc \u0634\u062f\u0647 \u0627\u0633\u062a \u06a9\u0647 \u0645\u062a\u0634\u06a9\u0644 \u0627\u0632 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647 \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646 \u0628\u0627 \u06cc\u06a9 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0631\u0627\u0628\u0637\u0647 \u0627\u06cc \u0627\u0633\u062a \u0648 \u0628\u0627 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u0634\u062a\u0631\u06cc \u062c\u062f\u0627\u06af\u0627\u0646\u0647 \u0627\u0632 \u0637\u0631\u06cc\u0642 HTTP \u0627\u0631\u062a\u0628\u0627\u0637 \u0628\u0631\u0642\u0631\u0627\u0631 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0627\u0632 JWT \u0628\u0631\u0627\u06cc \u0627\u062d\u0631\u0627\u0632 \u0647\u0648\u06cc\u062a \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f.<\/strong> <\/p>\n<p>\u0633\u067e\u0633\u060c \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645\u06cc \u06a9\u0647 \u0627\u0632 a \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f \u0645\u062b\u0627\u0644 \u0645\u06cc \u0632\u0646\u0645 <strong>\u0631\u0648\u0628\u06cc \u0631\u0648\u06cc \u0631\u06cc\u0644<\/strong> GraphQL API\u060c \u062c\u0648\u0627\u0647\u0631 ActiveAdmin \u0628\u0631\u0627\u06cc \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u0627\u062f\u0645\u06cc\u0646\u060c \u0648 \u0641\u0631\u0627\u0646\u062a \u0627\u0646\u062f \u0633\u0627\u062e\u062a\u0647 \u0634\u062f\u0647 \u0628\u0627 NextJS (React). <\/p>\n<p>\u067e\u0633 \u0627\u062c\u0627\u0632\u0647 \u0628\u062f\u0647\u06cc\u062f \u0628\u0647 \u0627\u06cc\u0646 \u06a9\u0627\u0631 \u0628\u0631\u0633\u06cc\u0645! <\/p>\n<hr\/>\n<p>\u0627\u0628\u062a\u062f\u0627 \u0628\u0627\u06cc\u062f \u062e\u0648\u062f \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>impersonations<\/code> \u062c\u062f\u0648\u0644.  \u0645\u062f\u0644 \u062f\u0627\u062f\u0647 \u0634\u0645\u0627 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u062f\u0631 \u0646\u0647\u0627\u06cc\u062a \u0686\u06cc\u0632\u06cc \u0634\u0628\u06cc\u0647 \u0628\u0647 \u0627\u06cc\u0646 \u0628\u0627\u0634\u062f:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/07\/\u0648\u06cc\u0698\u06af\u06cc-\u062c\u0639\u0644-\u0647\u0648\u06cc\u062a-\u0628\u0627-\u0627\u0633\u062a\u0641\u0627\u062f\u0647-\u0627\u0632-Rails-\u0648-NextJS.jpeg\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"265\" title=\"\"><\/p>\n<p>\u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u062e\u0648\u0627\u0647\u06cc\u062f \u06cc\u06a9 \u0634\u0627\u062e\u0635 \u0648 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a \u0628\u0631\u0627\u06cc \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u0627\u0632 \u0622\u0646 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>token<\/code> \u0627\u0633\u062a <strong>\u0645\u0646\u062d\u0635\u0631 \u0628\u0641\u0631\u062f<\/strong>. <\/p>\n<p>\u062f\u0646\u0628\u0627\u0644\u0647 \u0628\u0647 \u0634\u0631\u062d \u0632\u06cc\u0631 \u0627\u0633\u062a:<br \/>\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u0645\u062f\u06cc\u0631 \u0631\u0648\u06cc \u062f\u06a9\u0645\u0647 &#8220;\u062c\u0639\u0644 \u0647\u0648\u06cc\u062a&#8221; \u06a9\u0644\u06cc\u06a9 \u0645\u06cc \u06a9\u0646\u062f:<\/p>\n<ol>\n<li>\u0628\u0627\u0637\u0646 \u06cc\u06a9 \u0631\u062f\u06cc\u0641 \u062c\u062f\u06cc\u062f \u0631\u0627 \u062f\u0631 \u0642\u0633\u0645\u062a \u0642\u0631\u0627\u0631 \u0645\u06cc \u062f\u0647\u062f <code>impersonations<\/code> \u062c\u062f\u0648\u0644\u060c \u06a9\u0647 \u06cc\u06a9 \u0645\u0631\u062c\u0639 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0647\u062f\u0641 \u0648 \u06cc\u06a9 \u0646\u0634\u0627\u0646\u0647 \u062a\u0635\u0627\u062f\u0641\u06cc \u0631\u0627 \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc \u06a9\u0646\u062f. <\/li>\n<li>\u0627\u062f\u0645\u06cc\u0646 \u0628\u0647 \u0645\u0633\u06cc\u0631 \u062e\u0627\u0635\u06cc \u062f\u0631 \u0641\u0631\u0627\u0646\u062a\u200c\u0627\u0646\u062f \u0647\u062f\u0627\u06cc\u062a \u0645\u06cc\u200c\u0634\u0648\u062f \u06a9\u0647 \u0634\u0627\u0645\u0644 \u0622\u0646 \u0631\u0645\u0632 \u0645\u0648\u0642\u062a \u062f\u0631 \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627\u06cc \u067e\u0631\u0633 \u0648 \u062c\u0648 \u0645\u06cc\u200c\u0634\u0648\u062f.<\/li>\n<li>\u0645\u0633\u06cc\u0631 \u0641\u0631\u0627\u0646\u062a\u200c\u0627\u0646\u062f \u0641\u0648\u0631\u0627\u064b \u0627\u0632 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u200c\u06a9\u0646\u062f \u062a\u0627 \u0627\u06cc\u0646 \u0631\u0645\u0632 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0645\u0648\u0642\u062a \u0631\u0627 \u0628\u0627 \u06cc\u06a9 JWT \u0648\u0627\u0642\u0639\u06cc \u0628\u0631\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u062c\u0639\u0644\u200c\u0634\u062f\u0647 \u0645\u0628\u0627\u062f\u0644\u0647 \u06a9\u0646\u062f.  \u0622\u0646 \u0631\u0627 \u062f\u0631 \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc \u062c\u0644\u0633\u0647 \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f \u0648 \u0628\u0647\u200c\u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0648\u0631\u0648\u062f \u0628\u0647 \u0633\u06cc\u0633\u062a\u0645 \u0639\u0627\u062f\u06cc \u0627\u062f\u0627\u0645\u0647 \u0645\u06cc\u200c\u062f\u0647\u062f. <\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/07\/1689495322_292_\u0648\u06cc\u0698\u06af\u06cc-\u062c\u0639\u0644-\u0647\u0648\u06cc\u062a-\u0628\u0627-\u0627\u0633\u062a\u0641\u0627\u062f\u0647-\u0627\u0632-Rails-\u0648-NextJS.png\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"510\" title=\"\"><\/p>\n<p><em>(\u062a\u0648\u062c\u0647: \u0646\u0645\u0648\u062f\u0627\u0631 \u062a\u0648\u0627\u0644\u06cc \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0631\u0627 \u0646\u0634\u0627\u0646 \u0645\u06cc\u200c\u062f\u0647\u062f \u0648 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u06cc\u06a9 REST API \u0628\u0631\u0627\u06cc \u0646\u0642\u0627\u0637 \u0627\u0646\u062a\u0647\u0627\u06cc\u06cc \u0645\u062f\u06cc\u0631\u06cc\u062a \u0648 \u06cc\u06a9 API GraphQL \u0628\u0631\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0635\u0644\u06cc frontend \u0631\u0627 \u0646\u0634\u0627\u0646 \u0645\u06cc\u200c\u062f\u0647\u062f. \u0628\u0627 \u0627\u06cc\u0646 \u062d\u0627\u0644\u060c \u062a\u0645\u0631\u06a9\u0632 \u0627\u06cc\u0646\u062c\u0627 \u0628\u0631 \u0631\u0648\u06cc \u062f\u0631\u06a9 \u062f\u0646\u0628\u0627\u0644\u0647 \u0628\u0647 \u062c\u0627\u06cc \u062c\u0632\u0626\u06cc\u0627\u062a \u0631\u0627\u0628\u0637\u200c\u0647\u0627\u06cc \u0646\u0642\u0627\u0637 \u067e\u0627\u06cc\u0627\u0646\u06cc \u0627\u0633\u062a. )<\/em><\/p>\n<hr\/>\n<p>\u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0647 \u0627\u062c\u0631\u0627\u06cc \u0627\u06cc\u0646 \u06a9\u0627\u0631 \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u0645. <\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%AD%D9%84%D9%87_1_%D9%85%D8%AF%D9%84_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\"><\/span>\n<p>  \u0645\u0631\u062d\u0644\u0647 1: \u0645\u062f\u0644 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0648\u0644 \u0627\u0632 \u0647\u0645\u0647\u060c \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0622\u0646 \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645 <strong>\u0645\u0647\u0627\u062c\u0631\u062a<\/strong> \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f <code>impersonations<\/code> \u062c\u062f\u0648\u0644:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"k\">class<\/span> <span class=\"nc\">CreateImpersonations<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ActiveRecord<\/span><span class=\"o\">::<\/span><span class=\"no\">Migration<\/span><span class=\"p\">[<\/span><span class=\"mf\">7.0<\/span><span class=\"p\">]<\/span>\n  <span class=\"k\">def<\/span> <span class=\"nf\">change<\/span>\n    <span class=\"n\">create_table<\/span> <span class=\"ss\">:impersonations<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">t<\/span><span class=\"o\">|<\/span>\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">references<\/span> <span class=\"ss\">:user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span> <span class=\"ss\">foreign_key: <\/span><span class=\"kp\">true<\/span>\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">references<\/span> <span class=\"ss\">:admin_user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span> <span class=\"ss\">foreign_key: <\/span><span class=\"kp\">true<\/span>\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">string<\/span> <span class=\"ss\">:token<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">datetime<\/span> <span class=\"ss\">:exchange_before<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">boolean<\/span> <span class=\"ss\">:used<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span> <span class=\"ss\">default: <\/span><span class=\"kp\">false<\/span>\n\n      <span class=\"n\">t<\/span><span class=\"p\">.<\/span><span class=\"nf\">timestamps<\/span>\n    <span class=\"k\">end<\/span>\n\n    <span class=\"n\">add_index<\/span> <span class=\"ss\">:impersonations<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:token<\/span><span class=\"p\">,<\/span> <span class=\"ss\">unique: <\/span><span class=\"kp\">true<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0645\u062f\u0644 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u0645:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"k\">class<\/span> <span class=\"nc\">Impersonation<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ApplicationRecord<\/span>\n  <span class=\"no\">SESSION_DURATION<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">20<\/span><span class=\"p\">.<\/span><span class=\"nf\">minutes<\/span>\n\n  <span class=\"n\">belongs_to<\/span> <span class=\"ss\">:user<\/span>\n  <span class=\"n\">belongs_to<\/span> <span class=\"ss\">:admin_user<\/span>\n\n  <span class=\"n\">validates<\/span> <span class=\"ss\">:token<\/span><span class=\"p\">,<\/span> <span class=\"ss\">presence: <\/span><span class=\"kp\">true<\/span><span class=\"p\">,<\/span> <span class=\"ss\">uniqueness: <\/span><span class=\"kp\">true<\/span>\n  <span class=\"n\">validates<\/span> <span class=\"ss\">:exchange_before<\/span><span class=\"p\">,<\/span> <span class=\"ss\">presence: <\/span><span class=\"kp\">true<\/span>\n\n  <span class=\"n\">scope<\/span> <span class=\"ss\">:current<\/span><span class=\"p\">,<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"p\">{<\/span> <span class=\"n\">where<\/span><span class=\"p\">(<\/span><span class=\"ss\">used: <\/span><span class=\"kp\">false<\/span><span class=\"p\">).<\/span><span class=\"nf\">where<\/span><span class=\"p\">(<\/span><span class=\"s1\">'exchange_before &gt;= ?'<\/span><span class=\"p\">,<\/span> <span class=\"no\">Time<\/span><span class=\"p\">.<\/span><span class=\"nf\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"k\">def<\/span> <span class=\"nf\">mark_used!<\/span>\n    <span class=\"n\">update!<\/span><span class=\"p\">(<\/span><span class=\"ss\">used: <\/span><span class=\"kp\">true<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"k\">def<\/span> <span class=\"nf\">session_duration<\/span>\n    <span class=\"no\">SESSION_DURATION<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0641\u0631\u0627\u0645\u0648\u0634 \u0646\u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0631\u0627\u0628\u0637\u0647 \u0631\u0627 \u062f\u0631 \u062c\u0647\u0627\u062a \u062f\u06cc\u06af\u0631 \u0646\u06cc\u0632 \u062a\u0639\u0631\u06cc\u0641 \u06a9\u0646\u06cc\u062f <code>user<\/code> \u0648 <code>admin_user<\/code> \u0645\u062f\u0644 \u0647\u0627. <\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%AD%D9%84%D9%87_2_%D8%AF%DA%A9%D9%85%D9%87_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\"><\/span>\n<p>  \u0645\u0631\u062d\u0644\u0647 2: \u062f\u06a9\u0645\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0647 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u062f\u06a9\u0645\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u06a9\u0627\u0631\u0628\u0631 \u062f\u0631 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u0645\u062f\u06cc\u0631\u06cc\u062a \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u0645.  \u0647\u0645\u0627\u0646\u0637\u0648\u0631 \u06a9\u0647 \u0627\u0634\u0627\u0631\u0647 \u06a9\u0631\u062f\u0645\u060c \u0645\u0646 \u0627\u0632 ActiveAdmin gem \u0628\u0631\u0627\u06cc \u0628\u06a9 \u0622\u0641\u06cc\u0633 \u0645\u062f\u06cc\u0631\u06cc\u062a \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u0645\u060c \u06a9\u0647 DSL \u062e\u0627\u0635 \u062e\u0648\u062f \u0631\u0627 \u0628\u0631\u0627\u06cc \u0627\u0641\u0632\u0648\u062f\u0646 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0633\u0641\u0627\u0631\u0634\u06cc \u0628\u0647 \u0645\u0646\u0627\u0628\u0639 \u062f\u0627\u0631\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># app\/admin\/users.rb<\/span>\n\n<span class=\"no\">ActiveAdmin<\/span><span class=\"p\">.<\/span><span class=\"nf\">register<\/span> <span class=\"no\">User<\/span> <span class=\"k\">do<\/span>\n  <span class=\"o\">...<\/span>\n\n  <span class=\"n\">member_action<\/span> <span class=\"ss\">:impersonate<\/span><span class=\"p\">,<\/span> <span class=\"ss\">method: :post<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">user<\/span> <span class=\"o\">=<\/span> <span class=\"no\">User<\/span><span class=\"p\">.<\/span><span class=\"nf\">find<\/span><span class=\"p\">(<\/span><span class=\"n\">params<\/span><span class=\"p\">[<\/span><span class=\"ss\">:id<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"n\">impersonator<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Initiator<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">user: <\/span><span class=\"n\">user<\/span><span class=\"p\">,<\/span>\n                                                        <span class=\"ss\">admin_user: <\/span><span class=\"n\">current_admin_user<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">initiate!<\/span>\n    <span class=\"n\">redirect_url<\/span> <span class=\"o\">=<\/span> <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">redirect_url<\/span>\n\n    <span class=\"n\">redirect_to<\/span> <span class=\"n\">redirect_url<\/span><span class=\"p\">,<\/span> <span class=\"ss\">allow_other_host: <\/span><span class=\"kp\">true<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">action_item<\/span> <span class=\"ss\">:impersonate<\/span><span class=\"p\">,<\/span> <span class=\"ss\">only: :show<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">link_to<\/span><span class=\"p\">(<\/span><span class=\"s1\">'Impersonate'<\/span><span class=\"p\">,<\/span> <span class=\"n\">impersonate_admin_user_path<\/span><span class=\"p\">(<\/span><span class=\"n\">resource<\/span><span class=\"p\">),<\/span>\n            <span class=\"ss\">method: :post<\/span><span class=\"p\">,<\/span> <span class=\"ss\">target: <\/span><span class=\"s1\">'_blank'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">rel: <\/span><span class=\"s1\">'noopener'<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u0646 \u062f\u0648\u0633\u062a \u062f\u0627\u0631\u0645 \u0627\u0632 \u0627\u0634\u06cc\u0627\u0621 \u0633\u0631\u0648\u06cc\u0633 SRP \u0648 \u06af\u0631\u0648\u0647 \u0628\u0646\u062f\u06cc \u06a9\u0644\u0627\u0633 \u0647\u0627 \u0628\u0631 \u0627\u0633\u0627\u0633 \u062f\u0627\u0645\u0646\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u0645\u060c \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u06cc\u06a9 \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0631\u062f\u0645 <code>Users::Impersonations::Initiator<\/code> \u06a9\u0644\u0627\u0633\u06cc \u06a9\u0647 \u0645\u0633\u0626\u0648\u0644 \u0627\u06cc\u062c\u0627\u062f <code>impersonation<\/code> \u062b\u0628\u062a \u0648 \u0628\u0631\u06af\u0631\u062f\u0627\u0646\u062f\u0646 <code>url<\/code> \u06a9\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0647\u062f\u0627\u06cc\u062a \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># This class builds a url that to allow an admin user to impersonate a user.<\/span>\n<span class=\"c1\"># It creates a temporary token that the frontend will exchange for a more permanent JWT<\/span>\n<span class=\"c1\"># in a subsequent call.<\/span>\n<span class=\"c1\"># Since this temporary token travels in the query params, it is insecure and therefore<\/span>\n<span class=\"c1\"># only valid for a couple minutes and can be used only once.<\/span>\n\n<span class=\"k\">module<\/span> <span class=\"nn\">Users<\/span>\n  <span class=\"k\">module<\/span> <span class=\"nn\">Impersonations<\/span>\n    <span class=\"k\">class<\/span> <span class=\"nc\">Initiator<\/span>\n      <span class=\"no\">EXCHANGE_EXPIRES_IN<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">2<\/span><span class=\"p\">.<\/span><span class=\"nf\">minutes<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">initialize<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">:,<\/span> <span class=\"n\">admin_user<\/span><span class=\"p\">:)<\/span>\n        <span class=\"vi\">@user<\/span> <span class=\"o\">=<\/span> <span class=\"n\">user<\/span>\n        <span class=\"vi\">@admin_user<\/span> <span class=\"o\">=<\/span> <span class=\"n\">admin_user<\/span>\n      <span class=\"k\">end<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">initiate!<\/span>\n        <span class=\"o\">::<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">create!<\/span><span class=\"p\">(<\/span><span class=\"ss\">user: <\/span><span class=\"n\">user<\/span><span class=\"p\">,<\/span>\n                                <span class=\"ss\">admin_user: <\/span><span class=\"n\">admin_user<\/span><span class=\"p\">,<\/span>\n                                <span class=\"ss\">token: <\/span><span class=\"n\">token<\/span><span class=\"p\">,<\/span>\n                                <span class=\"ss\">exchange_before: <\/span><span class=\"no\">EXCHANGE_EXPIRES_IN<\/span><span class=\"p\">.<\/span><span class=\"nf\">from_now<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">end<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">redirect_url<\/span>\n        <span class=\"n\">base_url<\/span> <span class=\"o\">=<\/span> <span class=\"no\">URI<\/span><span class=\"p\">.<\/span><span class=\"nf\">parse<\/span><span class=\"p\">(<\/span><span class=\"n\">frontend_url<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">base_url<\/span><span class=\"p\">.<\/span><span class=\"nf\">path<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'\/impersonate'<\/span>\n        <span class=\"n\">base_url<\/span><span class=\"p\">.<\/span><span class=\"nf\">query<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span> <span class=\"ss\">token: <\/span><span class=\"n\">token<\/span> <span class=\"p\">}.<\/span><span class=\"nf\">to_query<\/span>\n\n        <span class=\"n\">base_url<\/span><span class=\"p\">.<\/span><span class=\"nf\">to_s<\/span>\n      <span class=\"k\">end<\/span>\n\n      <span class=\"kp\">private<\/span>\n\n      <span class=\"nb\">attr_reader<\/span> <span class=\"ss\">:user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:admin_user<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">token<\/span>\n        <span class=\"vi\">@token<\/span> <span class=\"o\">||=<\/span> <span class=\"no\">SecureRandom<\/span><span class=\"p\">.<\/span><span class=\"nf\">hex<\/span><span class=\"p\">(<\/span><span class=\"mi\">32<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">end<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">frontend_url<\/span>\n        <span class=\"no\">ENV<\/span><span class=\"p\">.<\/span><span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"s1\">'FRONTEND_URL'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'https:\/\/app.village.com'<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">end<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%AD%D9%84%D9%87_3_%D9%85%D8%B3%DB%8C%D8%B1_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA_Frontend\"><\/span>\n<p>  \u0645\u0631\u062d\u0644\u0647 3: \u0645\u0633\u06cc\u0631 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a Frontend<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062d\u0627\u0644\u0627 \u0642\u0633\u0645\u062a \u0627\u0648\u0644 \u0633\u06a9\u0627\u0646\u0633 \u0631\u0627 \u0622\u0645\u0627\u062f\u0647 \u06a9\u0631\u062f\u0647 \u0627\u06cc\u0645.  \u0645\u0627 \u0628\u0627\u06cc\u062f \u0628\u0647 \u0633\u0645\u062a \u062c\u0644\u0648 \u062d\u0631\u06a9\u062a \u06a9\u0646\u06cc\u0645.  \u0645\u0627 \u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u0645 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0637\u0648\u0631\u06cc \u06a9\u0647 \u0636\u0631\u0628\u0647 <code>\/impersonate?token=xxx<\/code> \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u06cc \u0631\u0627 \u0628\u0647 \u0628\u0627\u0637\u0646 \u0627\u0631\u0633\u0627\u0644 \u0645\u06cc \u06a9\u0646\u062f\u060c \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u062c\u0644\u0633\u0647 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0631\u06af\u0634\u062a\u06cc \u0631\u0627 \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0628\u0647 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc \u0647\u062f\u0627\u06cc\u062a \u0645\u06cc \u06a9\u0646\u062f.  \u062f\u0631 \u0635\u0648\u0631\u062a\u06cc \u06a9\u0647 \u062c\u0644\u0633\u0647 \u0642\u0628\u0644\u06cc \u062f\u0631 \u062d\u0627\u0644 \u0627\u0646\u062c\u0627\u0645 \u0628\u0627\u0634\u062f\u060c \u0627\u0628\u062a\u062f\u0627 \u062e\u0631\u0648\u062c \u0627\u0632 \u0633\u06cc\u0633\u062a\u0645 \u0631\u0627 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0645\u0637\u0645\u0626\u0646 \u0634\u0648\u06cc\u0645 \u06a9\u0647 \u062a\u0645\u0627\u0645 \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u067e\u0633 \u0627\u0632 \u062e\u0631\u0648\u062c \u0627\u0632 \u0633\u06cc\u0633\u062a\u0645 \u0627\u0646\u062c\u0627\u0645 \u0634\u062f\u0647 \u0627\u0633\u062a. <\/p>\n<p>\u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062b\u0627\u0644\u060c \u062f\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 NextJS \u0645\u0627 \u0627\u06cc\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u0686\u06cc\u0632\u06cc \u0634\u0628\u06cc\u0647 \u0628\u0647 \u0627\u06cc\u0646 \u0628\u0627\u0634\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code><span class=\"c1\">\/\/ src\/pages\/impersonate\/index.js<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"o\">*<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">userActions<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">..\/..\/..\/store\/actions\/userActions<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">ImpersonatePage<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">dispatch<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useDispatch<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">router<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRouter<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">madeRequest<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"nx\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">impersonate<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">token<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">.<\/span><span class=\"nx\">token<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"nx\">madeRequest<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">token<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">madeRequest<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">await<\/span> <span class=\"nx\">dispatch<\/span><span class=\"p\">(<\/span><span class=\"nx\">userActions<\/span><span class=\"p\">.<\/span><span class=\"nx\">logout<\/span><span class=\"p\">({<\/span> <span class=\"na\">skipToast<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span> <span class=\"p\">}));<\/span> \n        <span class=\"k\">await<\/span> <span class=\"nx\">dispatch<\/span><span class=\"p\">(<\/span><span class=\"nx\">userActions<\/span><span class=\"p\">.<\/span><span class=\"nx\">impersonate<\/span><span class=\"p\">(<\/span><span class=\"nx\">token<\/span><span class=\"p\">));<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nx\">replace<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">\/<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">};<\/span>\n\n    <span class=\"nx\">impersonate<\/span><span class=\"p\">();<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">.<\/span><span class=\"nx\">token<\/span><span class=\"p\">]);<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"o\">&lt;<\/span><span class=\"nx\">Head<\/span><span class=\"o\">&gt;<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"nx\">title<\/span><span class=\"o\">&gt;<\/span><span class=\"nx\">MyApp<\/span> <span class=\"o\">|<\/span> <span class=\"nx\">Impersonating<\/span><span class=\"o\">&lt;<\/span><span class=\"sr\">\/title<\/span><span class=\"err\">&gt;\n<\/span>    <span class=\"o\">&lt;<\/span><span class=\"sr\">\/Head<\/span><span class=\"err\">&gt;\n<\/span>  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">ImpersonatePage<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0627\u0637\u0646 \u0645\u0646 \u06cc\u06a9 \u062c\u0647\u0634 graphQL \u0628\u0647 \u0646\u0627\u0645 \u0627\u0631\u0627\u0626\u0647 \u062e\u0648\u0627\u0647\u062f \u06a9\u0631\u062f <code>ImpersonateUser<\/code> \u06a9\u0647 \u062c\u0628\u0647\u0647 \u0627\u0633\u062a\u0646\u0627\u062f \u062e\u0648\u0627\u0647\u062f \u0634\u062f.  \u0627\u06cc\u0646 <code>jwt<\/code> \u06cc\u06a9 \u0641\u06cc\u0644\u062f \u0645\u0648\u062c\u0648\u062f \u062f\u0631 \u0646\u0648\u0639 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0631\u06af\u0634\u062a\u06cc \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code><span class=\"c1\">\/\/ store\/actions\/userActions.js<\/span>\n\n<span class=\"p\">...<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">impersonate<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">token<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"k\">async<\/span> <span class=\"p\">(<\/span><span class=\"nx\">dispatch<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getState<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">gqlQuery<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">query<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`\n      mutation ImpersonateUser($token: String!) {\n        impersonateUser(token: $token) {\n          errors\n          user {\n            id \n            jwt\n            name\n            email\n          }\n        }\n      }\n    `<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">variables<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">token<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">},<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">helper<\/span><span class=\"p\">(<\/span><span class=\"nx\">gqlQuery<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">responseData<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">impersonateUser<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">errors<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">responseData<\/span><span class=\"p\">.<\/span><span class=\"nx\">errors<\/span><span class=\"p\">;<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userData<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">responseData<\/span><span class=\"p\">.<\/span><span class=\"nx\">user<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">errors<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">dispatch<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"nx\">USER_IMPERSONATION<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">userInfo<\/span><span class=\"p\">:<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"k\">await<\/span> <span class=\"nx\">handleSuccessfulUserLogin<\/span><span class=\"p\">(<\/span><span class=\"nx\">dispatch<\/span><span class=\"p\">,<\/span> <span class=\"nx\">getState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">userData<\/span><span class=\"p\">);<\/span> <span class=\"c1\">\/\/ Do your thing here...<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">dispatch<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"nx\">USER_IMPERSONATION_FAIL<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">errors<\/span><span class=\"p\">:<\/span> <span class=\"nx\">errors<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"nx\">errorMessageExtractor<\/span><span class=\"p\">(<\/span><span class=\"nx\">errors<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">dispatch<\/span><span class=\"p\">({<\/span>\n      <span class=\"na\">type<\/span><span class=\"p\">:<\/span> <span class=\"nx\">USER_IMPERSONATION_FAIL<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">errors<\/span><span class=\"p\">:<\/span> <span class=\"nx\">err<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">});<\/span>\n\n    <span class=\"nx\">handleServerErrors<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%AD%D9%84%D9%87_4_%D9%86%D9%82%D8%B7%D9%87_%D9%BE%D8%A7%DB%8C%D8%A7%D9%86%DB%8C_Backend_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%AA%D8%A8%D8%A7%D8%AF%D9%84_%D9%86%D8%B4%D8%A7%D9%86%D9%87_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA\"><\/span>\n<p>  \u0645\u0631\u062d\u0644\u0647 4: \u0646\u0642\u0637\u0647 \u067e\u0627\u06cc\u0627\u0646\u06cc Backend \u0628\u0631\u0627\u06cc \u062a\u0628\u0627\u062f\u0644 \u0646\u0634\u0627\u0646\u0647 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062c\u0647\u0634 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u0686\u06cc\u0632\u06cc \u0634\u0628\u06cc\u0647 \u0628\u0647 \u0627\u06cc\u0646 \u0628\u0627\u0634\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># app\/graphql\/mutations\/user\/impersonate_user.rb<\/span>\n\n<span class=\"c1\"># Given a temporary impersonation token,<\/span>\n<span class=\"c1\"># allows retrieving a CurrentUser (and its corresponding longer-lasting JWT)<\/span>\n\n<span class=\"k\">module<\/span> <span class=\"nn\">Mutations<\/span>\n  <span class=\"k\">module<\/span> <span class=\"nn\">User<\/span>\n    <span class=\"k\">class<\/span> <span class=\"nc\">ImpersonateUser<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">Mutations<\/span><span class=\"o\">::<\/span><span class=\"no\">BaseMutation<\/span>\n      <span class=\"n\">argument<\/span> <span class=\"ss\">:token<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">required: <\/span><span class=\"kp\">true<\/span>\n\n      <span class=\"n\">field<\/span> <span class=\"ss\">:user<\/span><span class=\"p\">,<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">CurrentUserType<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">true<\/span>\n      <span class=\"n\">field<\/span> <span class=\"ss\">:errors<\/span><span class=\"p\">,<\/span> <span class=\"no\">Types<\/span><span class=\"o\">::<\/span><span class=\"no\">JsonType<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">true<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">resolve<\/span><span class=\"p\">(<\/span><span class=\"n\">token<\/span><span class=\"p\">:)<\/span>\n        <span class=\"n\">impersonator<\/span> <span class=\"o\">=<\/span> <span class=\"o\">::<\/span><span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Authenticator<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">impersonation_token: <\/span><span class=\"n\">token<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">authenticate<\/span>\n\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"ss\">errors: <\/span><span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">errors<\/span> <span class=\"p\">}<\/span> <span class=\"k\">unless<\/span> <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">success?<\/span>\n\n        <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:current_user<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">user<\/span>\n        <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">impersonation<\/span>\n\n        <span class=\"p\">{<\/span> <span class=\"ss\">user: <\/span><span class=\"n\">impersonator<\/span><span class=\"p\">.<\/span><span class=\"nf\">user<\/span> <span class=\"p\">}<\/span>\n      <span class=\"k\">end<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nc\">self<\/span><span class=\"o\">.<\/span><span class=\"nf\">authorized?<\/span><span class=\"p\">(<\/span><span class=\"n\">_object<\/span><span class=\"p\">,<\/span> <span class=\"n\">_context<\/span><span class=\"p\">)<\/span>\n        <span class=\"kp\">true<\/span> <span class=\"c1\"># needed because my BaseMutation requires a signed in user by default, so we're overriding. <\/span>\n      <span class=\"k\">end<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u0646 <code>Types::CurrentUserType<\/code> \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u0686\u06cc\u0632\u06cc \u0634\u0628\u06cc\u0647 \u0628\u0647 \u0627\u06cc\u0646 \u0628\u0627\u0634\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># app\/graphql\/types\/current_user_type.rb<\/span>\n\n<span class=\"k\">module<\/span> <span class=\"nn\">Types<\/span>\n  <span class=\"k\">class<\/span> <span class=\"nc\">CurrentUserType<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">ApplicationRecordType<\/span>\n    <span class=\"n\">field<\/span> <span class=\"ss\">:id<\/span><span class=\"p\">,<\/span> <span class=\"no\">ID<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\n    <span class=\"n\">field<\/span> <span class=\"ss\">:name<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\n    <span class=\"n\">field<\/span> <span class=\"ss\">:email<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">false<\/span>\n\n    <span class=\"n\">field<\/span> <span class=\"ss\">:jwt<\/span><span class=\"p\">,<\/span> <span class=\"no\">String<\/span><span class=\"p\">,<\/span> <span class=\"ss\">null: <\/span><span class=\"kp\">true<\/span>\n\n    <span class=\"k\">def<\/span> <span class=\"nf\">jwt<\/span>\n      <span class=\"k\">if<\/span> <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">].<\/span><span class=\"nf\">present?<\/span>\n        <span class=\"no\">AuthToken<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"p\">(<\/span><span class=\"n\">object<\/span><span class=\"p\">,<\/span> <span class=\"ss\">expires_in: <\/span><span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">].<\/span><span class=\"nf\">session_duration<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">else<\/span>\n        <span class=\"no\">AuthToken<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"p\">(<\/span><span class=\"n\">object<\/span><span class=\"p\">)<\/span>\n      <span class=\"k\">end<\/span>\n    <span class=\"k\">end<\/span>\n\n    <span class=\"k\">def<\/span> <span class=\"nc\">self<\/span><span class=\"o\">.<\/span><span class=\"nf\">authorized?<\/span><span class=\"p\">(<\/span><span class=\"n\">object<\/span><span class=\"p\">,<\/span> <span class=\"n\">context<\/span><span class=\"p\">)<\/span>\n      <span class=\"n\">context<\/span><span class=\"p\">[<\/span><span class=\"ss\">:current_user<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"n\">object<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0627\u0632 \u0627\u0647\u0631\u0645 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>context[:impersonation]<\/code> \u06a9\u0647 \u0631\u0648\u06cc \u062c\u0647\u0634 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0631\u062f\u06cc\u0645\u060c \u062a\u0627 \u0622\u0646 \u0631\u0627 \u0637\u0648\u0631\u06cc \u06a9\u0646\u06cc\u0645 \u06a9\u0647 \u062c\u0644\u0633\u0627\u062a \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0628\u0647\u200c\u062c\u0627\u06cc \u062d\u0627\u0644\u062a \u067e\u06cc\u0634\u200c\u0641\u0631\u0636\u060c \u0641\u0642\u0637 20 \u062f\u0642\u06cc\u0642\u0647 \u0645\u0639\u062a\u0628\u0631 \u0628\u0627\u0634\u0646\u062f. <\/p>\n<p>\u0645\u0646 \u06a9\u0644\u0627\u0633 \u062e\u062f\u0645\u0627\u062a \u062f\u0627\u0631\u0645 <code>AuthToken<\/code> \u06a9\u0647 \u0645\u0646 \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f JWT \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u0645.  \u0645\u0646 \u0648\u0627\u0631\u062f \u062c\u0632\u0626\u06cc\u0627\u062a \u0622\u0646 \u0646\u0645\u06cc \u0634\u0648\u0645 \u0632\u06cc\u0631\u0627 \u062e\u0627\u0631\u062c \u0627\u0632 \u0645\u0648\u0636\u0648\u0639 \u0627\u0633\u062a. <\/p>\n<p>\u0648 \u0627\u06cc\u0646 \u0628\u0627\u06cc\u062f \u0628\u0627\u0634\u062f! <\/p>\n<hr\/>\n<h3><span class=\"ez-toc-section\" id=\"%D9%85%D8%B1%D8%AD%D9%84%D9%87_5_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7\"><\/span>\n<p>  \u0645\u0631\u062d\u0644\u0647 5: \u062a\u0633\u062a \u0647\u0627!<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062a\u0633\u062a \u0647\u0627\u06cc ActiveAdmin: \u062a\u0627\u06a9\u06cc\u062f \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u062f\u06a9\u0645\u0647 \u0646\u0634\u0627\u0646 \u0645\u06cc \u062f\u0647\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># spec\/controllers\/admin\/users_controller_spec.rb<\/span>\n\n<span class=\"no\">RSpec<\/span><span class=\"p\">.<\/span><span class=\"nf\">describe<\/span> <span class=\"no\">Admin<\/span><span class=\"o\">::<\/span><span class=\"no\">UsersController<\/span> <span class=\"k\">do<\/span>\n  <span class=\"n\">render_views<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:page<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"no\">Capybara<\/span><span class=\"o\">::<\/span><span class=\"no\">Node<\/span><span class=\"o\">::<\/span><span class=\"no\">Simple<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">body<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">describe<\/span> <span class=\"s1\">'GET show'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">subject<\/span><span class=\"p\">(<\/span><span class=\"ss\">:make_request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">get<\/span> <span class=\"ss\">:show<\/span><span class=\"p\">,<\/span> <span class=\"ss\">params: <\/span><span class=\"p\">{<\/span> <span class=\"ss\">id: <\/span><span class=\"n\">user<\/span><span class=\"p\">.<\/span><span class=\"nf\">id<\/span> <span class=\"p\">}<\/span> <span class=\"p\">}<\/span>\n    <span class=\"n\">let!<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n    <span class=\"n\">before<\/span> <span class=\"k\">do<\/span>\n      <span class=\"n\">login_admin<\/span>\n    <span class=\"k\">end<\/span>\n\n    <span class=\"n\">it<\/span> <span class=\"s1\">'renders the user info and button to impersonate'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:aggregate_failures<\/span> <span class=\"k\">do<\/span>\n      <span class=\"n\">make_request<\/span>\n\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">response<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">have_http_status<\/span><span class=\"p\">(<\/span><span class=\"ss\">:success<\/span><span class=\"p\">)<\/span>\n\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">have_content<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">.<\/span><span class=\"nf\">first_name<\/span><span class=\"p\">)<\/span>\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">have_content<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">.<\/span><span class=\"nf\">last_name<\/span><span class=\"p\">)<\/span>\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">have_content<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">.<\/span><span class=\"nf\">email<\/span><span class=\"p\">)<\/span>\n\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">have_link<\/span><span class=\"p\">(<\/span><span class=\"s1\">'Impersonate'<\/span><span class=\"p\">,<\/span> <span class=\"ss\">href: <\/span><span class=\"n\">impersonate_admin_user_path<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">))<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span> \n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0622\u0632\u0645\u0648\u0646 \u06a9\u0644\u0627\u0633 \u062e\u062f\u0645\u0627\u062a \u0622\u063a\u0627\u0632\u06af\u0631:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># spec\/concepts\/users\/impersonations\/initiator_spec.rb<\/span>\n\n<span class=\"no\">RSpec<\/span><span class=\"p\">.<\/span><span class=\"nf\">describe<\/span> <span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Initiator<\/span> <span class=\"k\">do<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:initiator<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">described_class<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">user: <\/span><span class=\"n\">user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">admin_user: <\/span><span class=\"n\">admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">before<\/span> <span class=\"k\">do<\/span>\n    <span class=\"no\">ENV<\/span><span class=\"p\">[<\/span><span class=\"s1\">'FRONTEND_URL'<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'https:\/\/my-frontend.com'<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">after<\/span> <span class=\"k\">do<\/span>\n    <span class=\"no\">ENV<\/span><span class=\"p\">[<\/span><span class=\"s1\">'FRONTEND_URL'<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">it<\/span> <span class=\"s1\">'creates an impersonation and exposes a redirect url'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">expect<\/span> <span class=\"p\">{<\/span>\n      <span class=\"n\">initiator<\/span><span class=\"p\">.<\/span><span class=\"nf\">initiate!<\/span>\n    <span class=\"p\">}.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">change<\/span><span class=\"p\">(<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:count<\/span><span class=\"p\">).<\/span><span class=\"nf\">by<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">impersonation<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">last<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">user<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">admin_user<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">admin_user<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_present<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">exchange_before<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_present<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">initiator<\/span><span class=\"p\">.<\/span><span class=\"nf\">redirect_url<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"https:\/\/my-frontend.com\/impersonate?token=<\/span><span class=\"si\">#{<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062a\u0633\u062a \u0648\u0627\u062d\u062f \u062c\u0647\u0634:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># spec\/graphql\/mutations\/user\/impersonate_user_spec.rb<\/span>\n\n<span class=\"no\">RSpec<\/span><span class=\"p\">.<\/span><span class=\"nf\">describe<\/span> <span class=\"no\">Mutations<\/span><span class=\"o\">::<\/span><span class=\"no\">User<\/span><span class=\"o\">::<\/span><span class=\"no\">ImpersonateUser<\/span><span class=\"p\">,<\/span> <span class=\"ss\">type: :request<\/span> <span class=\"k\">do<\/span>\n  <span class=\"n\">subject<\/span><span class=\"p\">(<\/span><span class=\"ss\">:make_request<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">make_graphql_request<\/span><span class=\"p\">(<\/span>\n      <span class=\"ss\">query: <\/span><span class=\"n\">query<\/span><span class=\"p\">,<\/span>\n      <span class=\"ss\">variables: <\/span><span class=\"n\">variables<\/span>\n    <span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"kp\">nil<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:query<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n    <span class=\"o\">&lt;&lt;-<\/span><span class=\"no\">GRAPHQL<\/span><span class=\"sh\">\n      mutation impersonateUser($token: String!) {\n        impersonateUser(token: $token) {\n          errors\n          user {\n            email\n            jwt\n            isVerified\n          }\n        }\n      }\n<\/span><span class=\"no\">    GRAPHQL<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:variables<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"ss\">token: <\/span><span class=\"n\">impersonation_token<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonation_token<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"s1\">'sometoken'<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:authenticator_double<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">instance_double<\/span><span class=\"p\">(<\/span><span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Authenticator<\/span><span class=\"p\">,<\/span>\n                    <span class=\"ss\">authenticate: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">,<\/span>\n                    <span class=\"ss\">success?: <\/span><span class=\"kp\">true<\/span><span class=\"p\">,<\/span>\n                    <span class=\"ss\">errors: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">,<\/span>\n                    <span class=\"ss\">user: <\/span><span class=\"n\">impersonated_user<\/span><span class=\"p\">,<\/span>\n                    <span class=\"ss\">impersonation: <\/span><span class=\"n\">stubbed_impersonation<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:stubbed_impersonation<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">user: <\/span><span class=\"n\">impersonated_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonated_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">before<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">allow<\/span><span class=\"p\">(<\/span><span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Authenticator<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">receive<\/span><span class=\"p\">(<\/span><span class=\"ss\">:new<\/span><span class=\"p\">).<\/span><span class=\"nf\">with<\/span><span class=\"p\">(<\/span><span class=\"ss\">impersonation_token: <\/span><span class=\"n\">impersonation_token<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">and_return<\/span><span class=\"p\">(<\/span><span class=\"n\">authenticator_double<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">allow<\/span><span class=\"p\">(<\/span><span class=\"no\">AuthToken<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">receive<\/span><span class=\"p\">(<\/span><span class=\"ss\">:token<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">with<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonated_user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">expires_in: <\/span><span class=\"mi\">20<\/span><span class=\"p\">.<\/span><span class=\"nf\">minutes<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">and_return<\/span><span class=\"p\">(<\/span><span class=\"s1\">'somejwt'<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">it<\/span> <span class=\"s1\">'returns verified user'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">make_request<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">json_body<\/span><span class=\"p\">.<\/span><span class=\"nf\">dig<\/span><span class=\"p\">(<\/span><span class=\"s1\">'impersonateUser'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'errors'<\/span><span class=\"p\">)).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_nil<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">json_body<\/span><span class=\"p\">.<\/span><span class=\"nf\">dig<\/span><span class=\"p\">(<\/span><span class=\"s1\">'impersonateUser'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'user'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'jwt'<\/span><span class=\"p\">)).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"s1\">'somejwt'<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">json_body<\/span><span class=\"p\">.<\/span><span class=\"nf\">dig<\/span><span class=\"p\">(<\/span><span class=\"s1\">'impersonateUser'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'user'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'email'<\/span><span class=\"p\">)).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonated_user<\/span><span class=\"p\">.<\/span><span class=\"nf\">email<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">context<\/span> <span class=\"s1\">'when the authenticator returns an error'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:error_message<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"s1\">'some error'<\/span> <span class=\"p\">}<\/span>\n\n    <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:authenticator_double<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span>\n      <span class=\"n\">instance_double<\/span><span class=\"p\">(<\/span><span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Authenticator<\/span><span class=\"p\">,<\/span>\n                      <span class=\"ss\">authenticate: <\/span><span class=\"kp\">nil<\/span><span class=\"p\">,<\/span>\n                      <span class=\"ss\">success?: <\/span><span class=\"kp\">false<\/span><span class=\"p\">,<\/span>\n                      <span class=\"ss\">errors: <\/span><span class=\"p\">{<\/span> <span class=\"ss\">impersonationToken: <\/span><span class=\"n\">error_message<\/span> <span class=\"p\">})<\/span>\n    <span class=\"k\">end<\/span>\n\n    <span class=\"n\">it<\/span> <span class=\"s1\">'returns the error'<\/span> <span class=\"k\">do<\/span>\n      <span class=\"n\">make_request<\/span>\n\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">json_body<\/span><span class=\"p\">.<\/span><span class=\"nf\">dig<\/span><span class=\"p\">(<\/span><span class=\"s1\">'impersonateUser'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'errors'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'impersonationToken'<\/span><span class=\"p\">)).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">error_message<\/span><span class=\"p\">)<\/span>\n      <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">json_body<\/span><span class=\"p\">.<\/span><span class=\"nf\">dig<\/span><span class=\"p\">(<\/span><span class=\"s1\">'impersonateUser'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'user'<\/span><span class=\"p\">)).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_nil<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062a\u0633\u062a \u062e\u062f\u0645\u0627\u062a \u0622\u063a\u0627\u0632\u06af\u0631:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"c1\"># spec\/concepts\/users\/impersonations\/initiator_spec.rb<\/span>\n\n<span class=\"no\">RSpec<\/span><span class=\"p\">.<\/span><span class=\"nf\">describe<\/span> <span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">Initiator<\/span> <span class=\"k\">do<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:initiator<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">described_class<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span><span class=\"p\">(<\/span><span class=\"ss\">user: <\/span><span class=\"n\">user<\/span><span class=\"p\">,<\/span> <span class=\"ss\">admin_user: <\/span><span class=\"n\">admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:admin_user<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">before<\/span> <span class=\"k\">do<\/span>\n    <span class=\"no\">ENV<\/span><span class=\"p\">[<\/span><span class=\"s1\">'FRONTEND_URL'<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'https:\/\/village-frontend.com'<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">after<\/span> <span class=\"k\">do<\/span>\n    <span class=\"no\">ENV<\/span><span class=\"p\">[<\/span><span class=\"s1\">'FRONTEND_URL'<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span>\n  <span class=\"k\">end<\/span>\n\n  <span class=\"n\">it<\/span> <span class=\"s1\">'creates an impersonation and exposes a redirect url'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">expect<\/span> <span class=\"p\">{<\/span>\n      <span class=\"n\">initiator<\/span><span class=\"p\">.<\/span><span class=\"nf\">initiate!<\/span>\n    <span class=\"p\">}.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">change<\/span><span class=\"p\">(<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:count<\/span><span class=\"p\">).<\/span><span class=\"nf\">by<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">impersonation<\/span> <span class=\"o\">=<\/span> <span class=\"no\">Impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">last<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">user<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">user<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">admin_user<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"n\">admin_user<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_present<\/span>\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">exchange_before<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">be_present<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"n\">initiator<\/span><span class=\"p\">.<\/span><span class=\"nf\">redirect_url<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">eq<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"https:\/\/village-frontend.com\/impersonate?token=<\/span><span class=\"si\">#{<\/span><span class=\"n\">impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">token<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<h3><span class=\"ez-toc-section\" id=\"%D9%BE%D8%A7%D8%AF%D8%A7%D8%B4_%DA%A9%D8%A7%D8%B1%DA%AF%D8%B1_%D8%A8%D8%B1%D8%A7%DB%8C_%D9%BE%D8%A7%DA%A9_%DA%A9%D8%B1%D8%AF%D9%86_%D8%B3%D9%88%D8%A7%D8%A8%D9%82_%D8%AC%D8%B9%D9%84_%D9%87%D9%88%DB%8C%D8%AA_%D9%82%D8%AF%DB%8C%D9%85%DB%8C\"><\/span>\n<p>  \u067e\u0627\u062f\u0627\u0634: \u06a9\u0627\u0631\u06af\u0631 \u0628\u0631\u0627\u06cc \u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0633\u0648\u0627\u0628\u0642 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0642\u062f\u06cc\u0645\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0627\u0634\u062a\u0646 \u0633\u0648\u0627\u0628\u0642 \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0642\u062f\u06cc\u0645\u06cc \u062f\u0631 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u06cc\u06a9 \u0645\u0633\u06cc\u0631 \u062d\u0633\u0627\u0628\u0631\u0633\u06cc \u062e\u0648\u0628\u06cc \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u06a9\u0646\u062f \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u0631\u0627\u06cc \u0627\u0634\u06a9\u0627\u0644 \u0632\u062f\u0627\u06cc\u06cc \u0648 \u0645\u0645\u06cc\u0632\u06cc \u0645\u0641\u06cc\u062f \u0628\u0627\u0634\u062f.  \u0628\u0627 \u0627\u06cc\u0646 \u062d\u0627\u0644\u060c \u0627\u06af\u0631 \u06af\u0632\u0627\u0631\u0634\u200c\u0647\u0627 \u0628\u0631\u0627\u06cc \u0634\u0645\u0627 \u06a9\u0627\u0641\u06cc \u0647\u0633\u062a\u0646\u062f\u060c \u0634\u0627\u06cc\u062f \u062a\u0631\u062c\u06cc\u062d \u0645\u06cc\u200c\u062f\u0647\u06cc\u062f \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0648\u0631\u0647\u200c\u0627\u06cc \u0627\u06cc\u0646 \u0633\u0648\u0627\u0628\u0642 \u0631\u0627 \u067e\u0627\u06a9 \u06a9\u0646\u06cc\u062f \u0648 \u0645\u0642\u062f\u0627\u0631\u06cc \u0641\u0636\u0627\u06cc DB \u0631\u0627 \u0622\u0632\u0627\u062f \u06a9\u0646\u06cc\u062f.  \u062f\u0631 \u0622\u0646 \u0635\u0648\u0631\u062a\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u06cc\u06a9 \u06a9\u0627\u0631 \u0632\u0645\u0627\u0646\u200c\u0628\u0646\u062f\u06cc \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0648\u0631\u0647\u200c\u0627\u06cc \u0627\u062c\u0631\u0627 \u0645\u06cc\u200c\u0634\u0648\u062f. <\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0627\u0646\u062c\u0627\u0645 \u06a9\u0627\u0631\u0645 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 sidekiq \u0622\u0645\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code><span class=\"n\">app<\/span><span class=\"o\">\/<\/span><span class=\"n\">concepts<\/span><span class=\"o\">\/<\/span><span class=\"n\">users<\/span><span class=\"o\">\/<\/span><span class=\"n\">impersonations<\/span><span class=\"o\">\/<\/span><span class=\"n\">cleaner_worker<\/span><span class=\"p\">.<\/span><span class=\"nf\">rb<\/span>\n\n<span class=\"c1\"># Removes expired or already used impersonation tokens in order to free database space.<\/span>\n\n<span class=\"k\">module<\/span> <span class=\"nn\">Users<\/span>\n  <span class=\"k\">module<\/span> <span class=\"nn\">Impersonations<\/span>\n    <span class=\"k\">class<\/span> <span class=\"nc\">CleanerWorker<\/span>\n      <span class=\"kp\">include<\/span> <span class=\"no\">Sidekiq<\/span><span class=\"o\">::<\/span><span class=\"no\">Worker<\/span>\n\n      <span class=\"k\">def<\/span> <span class=\"nf\">perform<\/span>\n        <span class=\"o\">::<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">no_longer_valid<\/span><span class=\"p\">.<\/span><span class=\"nf\">destroy_all<\/span>\n      <span class=\"k\">end<\/span>\n    <span class=\"k\">end<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0648 \u0645\u0646 \u0627\u06cc\u0646 \u0645\u062d\u062f\u0648\u062f\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0645 <code>Impersonation<\/code>:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code>  <span class=\"n\">scope<\/span> <span class=\"ss\">:no_longer_valid<\/span><span class=\"p\">,<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"p\">{<\/span> <span class=\"n\">where<\/span><span class=\"p\">(<\/span><span class=\"ss\">used: <\/span><span class=\"kp\">true<\/span><span class=\"p\">).<\/span><span class=\"nf\">or<\/span><span class=\"p\">(<\/span><span class=\"n\">where<\/span><span class=\"p\">(<\/span><span class=\"s1\">'exchange_before &lt; ?'<\/span><span class=\"p\">,<\/span> <span class=\"no\">Time<\/span><span class=\"p\">.<\/span><span class=\"nf\">current<\/span><span class=\"p\">))<\/span> <span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062a\u0633\u062a \u0646\u06cc\u0632 \u0628\u0633\u06cc\u0627\u0631 \u0633\u0627\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight ruby\"><code>\n<span class=\"no\">RSpec<\/span><span class=\"p\">.<\/span><span class=\"nf\">describe<\/span> <span class=\"no\">Users<\/span><span class=\"o\">::<\/span><span class=\"no\">Impersonations<\/span><span class=\"o\">::<\/span><span class=\"no\">CleanerWorker<\/span> <span class=\"k\">do<\/span>\n  <span class=\"n\">let<\/span><span class=\"p\">(<\/span><span class=\"ss\">:worker<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">described_class<\/span><span class=\"p\">.<\/span><span class=\"nf\">new<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">let!<\/span><span class=\"p\">(<\/span><span class=\"ss\">:expired_impersonation<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:expired<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n  <span class=\"n\">let!<\/span><span class=\"p\">(<\/span><span class=\"ss\">:used_impersonation<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:used<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n  <span class=\"n\">let!<\/span><span class=\"p\">(<\/span><span class=\"ss\">:valid_impersonation<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"ss\">:impersonation<\/span><span class=\"p\">)<\/span> <span class=\"p\">}<\/span>\n\n  <span class=\"n\">it<\/span> <span class=\"s1\">'removes expired or already used impersonation tokens'<\/span> <span class=\"k\">do<\/span>\n    <span class=\"n\">expect<\/span> <span class=\"p\">{<\/span>\n      <span class=\"n\">worker<\/span><span class=\"p\">.<\/span><span class=\"nf\">perform<\/span>\n    <span class=\"p\">}.<\/span><span class=\"nf\">to<\/span> <span class=\"n\">change<\/span><span class=\"p\">(<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:count<\/span><span class=\"p\">).<\/span><span class=\"nf\">by<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">expect<\/span><span class=\"p\">(<\/span><span class=\"no\">Impersonation<\/span><span class=\"p\">.<\/span><span class=\"nf\">all<\/span><span class=\"p\">).<\/span><span class=\"nf\">to<\/span> <span class=\"n\">contain_exactly<\/span><span class=\"p\">(<\/span><span class=\"n\">valid_impersonation<\/span><span class=\"p\">)<\/span>\n  <span class=\"k\">end<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<hr\/>\n<p>\u0627\u0645\u06cc\u062f\u0648\u0627\u0631\u0645 \u0627\u06cc\u0646 \u0645\u0648\u0636\u0648\u0639 \u0628\u0647 \u0634\u0645\u0627 \u0627\u0644\u0647\u0627\u0645 \u062f\u0647\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0648\u06cc\u0698\u06af\u06cc \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f.  \u0627\u06cc\u0646 \u0648\u0627\u0642\u0639\u0627\u064b \u06cc\u06a9 \u0648\u06cc\u0698\u06af\u06cc \u0628\u0633\u06cc\u0627\u0631 \u0633\u0627\u062f\u0647 \u0627\u0633\u062a \u06a9\u0647 \u0627\u06a9\u062b\u0631 \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc SaaS \u062f\u0627\u0631\u0646\u062f.  \u0634\u0645\u0627 \u0646\u06cc\u0627\u0632\u06cc \u0628\u0647 \u062a\u062e\u06cc\u0644 \u0648 \u0627\u062e\u062a\u0631\u0627\u0639 \u0645\u062c\u062f\u062f \u0686\u0631\u062e \u0646\u062f\u0627\u0631\u06cc\u062f. <\/p>\n<p>\u0627\u0645\u0627 \u0635\u0627\u062f\u0642\u0627\u0646\u0647 \u0628\u06af\u0648\u06cc\u0645\u060c \u0645\u0646 \u0641\u0642\u0637 \u0627\u0632 \u0627\u06cc\u0646 \u067e\u0633\u062a \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0628\u0647\u0627\u0646\u0647\u200c\u0627\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0631\u062f\u0645 \u062a\u0627 \u0645\u062b\u0627\u0644\u06cc \u0628\u0632\u0646\u0645 \u06a9\u0647 \u0641\u06a9\u0631 \u0645\u06cc\u200c\u06a9\u0646\u0645 \u0627\u0634\u06cc\u0627\u0621 \u062e\u062f\u0645\u0627\u062a\u06cc \u062e\u0648\u0628 \u0686\u06af\u0648\u0646\u0647 \u0647\u0633\u062a\u0646\u062f \u0648 \u0631\u0648\u06cc\u06a9\u0631\u062f\u0645 \u0628\u0647 \u062c\u0647\u0634\u200c\u0647\u0627\u06cc \u062a\u0633\u062a \u0648\u0627\u062d\u062f.  \u0628\u0647 \u0633\u0644\u0627\u0645\u062a\u06cc!  \u2728<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u0628\u0647 \u0634\u0645\u0627 \u0646\u0634\u0627\u0646 \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f \u0628\u0647 \u0627\u062f\u0645\u06cc\u0646 \u0647\u0627\u06cc \u062f\u0627\u062e\u0644\u06cc \u062e\u0648\u062f \u0627\u062c\u0627\u0632\u0647 \u062f\u0647\u06cc\u062f \u062c\u0639\u0644 \u0647\u0648\u06cc\u062a \u06cc\u06a9 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u062c\u0639\u0644 \u06a9\u0646\u0646\u062f. \ud83e\udd77 \u0627\u06cc\u0646 \u06cc\u06a9 \u0648\u06cc\u0698\u06af\u06cc \u0641\u0648\u0642\u200c\u0627\u0644\u0639\u0627\u062f\u0647 \u0627\u0631\u0632\u0634\u0645\u0646\u062f \u0627\u0633\u062a \u06a9\u0647 \u0627\u06a9\u062b\u0631 \u0634\u0631\u06a9\u062a\u200c\u0647\u0627\u06cc SaaS \u0628\u0631\u0627\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0628\u0647\u062a\u0631 \u0627\u0632 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u200c\u0647\u0627\u06cc \u0645\u0634\u062a\u0631\u06cc\u060c \u0628\u0627 \u0622\u0646 \u062d\u0633\u0627\u0628 \u0645\u06cc\u200c\u06a9\u0646\u0646\u062f. \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc &hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-30697","post","type-post","status-publish","format-standard","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/30697","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=30697"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/30697\/revisions"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=30697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=30697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=30697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}