অ্যাপ ইঞ্জিন ব্যবহারকারী পরিষেবা থেকে ক্লাউড আইডেন্টিটি প্ল্যাটফর্মে স্থানান্তর করুন (মডিউল 21)

১. সংক্ষিপ্ত বিবরণ

সার্ভারলেস মাইগ্রেশন স্টেশন সিরিজের কোডল্যাব (স্ব-গতিতে শেখার উপযোগী টিউটোরিয়াল) এবং সম্পর্কিত ভিডিওগুলোর লক্ষ্য হলো গুগল ক্লাউড সার্ভারলেস ডেভেলপারদের এক বা একাধিক মাইগ্রেশনের মাধ্যমে তাদের অ্যাপ্লিকেশনগুলোকে আধুনিক করে তুলতে সাহায্য করা, যার মূল উদ্দেশ্য হলো পুরোনো সার্ভিসগুলো থেকে সরে আসা। এটি আপনার অ্যাপগুলোকে আরও সহজে বহনযোগ্য করে তোলে এবং আপনাকে আরও বেশি বিকল্প ও নমনীয়তা দেয়, যার ফলে আপনি আরও বিস্তৃত পরিসরের ক্লাউড প্রোডাক্টের সাথে ইন্টিগ্রেট করতে ও সেগুলো ব্যবহার করতে পারেন এবং নতুন ল্যাঙ্গুয়েজ রিলিজে আরও সহজে আপগ্রেড করতে পারেন। যদিও প্রাথমিকভাবে এই সিরিজটি ক্লাউডের একেবারে প্রথম দিকের ব্যবহারকারী, অর্থাৎ অ্যাপ ইঞ্জিন (স্ট্যান্ডার্ড এনভায়রনমেন্ট) ডেভেলপারদের উপর দৃষ্টি নিবদ্ধ করে তৈরি, তবে এর পরিধি এতটাই বিস্তৃত যে এটি ক্লাউড ফাংশনস এবং ক্লাউড রান- এর মতো অন্যান্য সার্ভারলেস প্ল্যাটফর্ম বা প্রযোজ্য ক্ষেত্রে অন্য প্ল্যাটফর্মগুলোকেও অন্তর্ভুক্ত করতে পারে।

এই কোডল্যাবের উদ্দেশ্য হলো পাইথন ২ অ্যাপ ইঞ্জিন ডেভেলপারদের দেখানো যে, কীভাবে অ্যাপ ইঞ্জিন ইউজার্স এপিআই/সার্ভিস থেকে ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম (GCIP)-এ মাইগ্রেট করতে হয়। এর সাথে ডেটাস্টোর অ্যাক্সেসের জন্য অ্যাপ ইঞ্জিন এনডিবি থেকে ক্লাউড এনডিবি -তে একটি অন্তর্নিহিত মাইগ্রেশনও রয়েছে (যা মূলত মাইগ্রেশন মডিউল ২-এ আলোচিত), এবং সেই সাথে পাইথন ৩-এ আপগ্রেডও করা হয়।

মডিউল ২০-এ আলোচনা করা হয়েছে কীভাবে মডিউল ১-এর স্যাম্পল অ্যাপে ইউজার্স এপিআই (Users API)-এর ব্যবহার যুক্ত করতে হয়। এই মডিউলে, আপনি মডিউল ২০-এর সম্পূর্ণ অ্যাপটি নিয়ে এর ব্যবহার ক্লাউড আইডেন্টিটি প্ল্যাটফর্মে (Cloud Identity Platform) স্থানান্তর করবেন।

আপনি শিখবেন কিভাবে

আপনার যা যা লাগবে

জরিপ

আপনি এই টিউটোরিয়ালটি কীভাবে ব্যবহার করবেন?

শুধু একবার পড়ে দেখুন এটি পড়ুন এবং অনুশীলনগুলো সম্পূর্ণ করুন।

পাইথন নিয়ে আপনার অভিজ্ঞতাকে আপনি কীভাবে মূল্যায়ন করবেন?

শিক্ষানবিশ মধ্যবর্তী দক্ষ

গুগল ক্লাউড পরিষেবা ব্যবহারের অভিজ্ঞতাকে আপনি কীভাবে মূল্যায়ন করবেন?

শিক্ষানবিশ মধ্যবর্তী দক্ষ

২. পটভূমি

অ্যাপ ইঞ্জিন ইউজার্স সার্ভিস হলো অ্যাপ ইঞ্জিন অ্যাপগুলোর ব্যবহারের জন্য একটি ইউজার অথেন্টিকেশন সিস্টেম। এটি আইডেন্টিটি প্রোভাইডার হিসেবে গুগল সাইন-ইন প্রদান করে, অ্যাপে ব্যবহারের জন্য সুবিধাজনক লগইন ও লগআউট লিঙ্ক দেয় এবং অ্যাডমিন ইউজার ও অ্যাডমিন-অনলি কার্যকারিতার ধারণা সমর্থন করে। অ্যাপ্লিকেশনের পোর্টেবিলিটি উন্নত করার জন্য, গুগল ক্লাউড পুরোনো অ্যাপ ইঞ্জিন বান্ডেলড সার্ভিসগুলো থেকে ক্লাউডের স্বতন্ত্র সার্ভিসগুলোতে মাইগ্রেট করার পরামর্শ দেয়, যেমন— ইউজার্স সার্ভিস থেকে ক্লাউড আইডেন্টিটি প্ল্যাটফর্মে মাইগ্রেট করা

আইডেন্টিটি প্ল্যাটফর্মটি ফায়ারবেস অথেন্টিকেশন-এর উপর ভিত্তি করে তৈরি এবং এতে মাল্টি-ফ্যাক্টর অথেন্টিকেশন, OIDC ও SAML SSO সাপোর্ট, মাল্টি-টেনেন্সি, ৯৯.৯৫% SLA-সহ আরও অনেক এন্টারপ্রাইজ ফিচার যুক্ত করা হয়েছে। আইডেন্টিটি প্ল্যাটফর্ম এবং ফায়ারবেস অথেন্টিকেশন-এর প্রোডাক্ট তুলনা পৃষ্ঠাতেও এই পার্থক্যগুলো তুলে ধরা হয়েছে। ইউজার্স সার্ভিস দ্বারা প্রদত্ত কার্যকারিতার তুলনায় উভয় প্রোডাক্টেই উল্লেখযোগ্যভাবে বেশি ফিচার রয়েছে।

এই মডিউল ২১ কোডল্যাবে অ্যাপের ইউজার অথেন্টিকেশনকে ইউজার্স সার্ভিস থেকে আইডেন্টিটি প্ল্যাটফর্মের ফিচারে পরিবর্তন করার পদ্ধতি দেখানো হয়েছে, যা মডিউল ২০-তে প্রদর্শিত কার্যকারিতার সবচেয়ে কাছাকাছি। এছাড়াও, মডিউল ২১-এ ডেটাস্টোর অ্যাক্সেসের জন্য অ্যাপ ইঞ্জিন এনডিবি থেকে ক্লাউড এনডিবি-তে মাইগ্রেশন দেখানো হয়েছে, যেখানে মডিউল ২-এর মাইগ্রেশনের পুনরাবৃত্তি করা হয়েছে।

যদিও মডিউল ২০-এর কোডটিকে একটি পাইথন ২ স্যাম্পল অ্যাপ হিসেবে "বিজ্ঞাপন" করা হয়েছে, এর সোর্স কোডটি পাইথন ২ এবং ৩ উভয়ের সাথেই সামঞ্জস্যপূর্ণ, এবং মডিউল ২১-এ আইডেন্টিটি প্ল্যাটফর্ম (এবং ক্লাউড এনডিবি)-এ মাইগ্রেট করার পরেও এটি তেমনই থাকে। পাইথন ৩-এ আপগ্রেড করার সময়ও ইউজার্স সার্ভিসটি ব্যবহার করা চালিয়ে যাওয়া সম্ভব, কারণ আইডেন্টিটি প্ল্যাটফর্মে মাইগ্রেট করা ঐচ্ছিক। পাইথন ৩-এর মতো দ্বিতীয় প্রজন্মের রানটাইমে আপগ্রেড করার সময় কীভাবে বান্ডেল করা সার্ভিসগুলো ব্যবহার করা চালিয়ে যেতে হয়, তা জানতে মডিউল ১৭-এর কোডল্যাব এবং ভিডিওটি দেখুন।

এই টিউটোরিয়ালটিতে নিম্নলিখিত ধাপগুলো রয়েছে:

  1. প্রস্তুতি/পূর্বপ্রস্তুতি
  2. কনফিগারেশন আপডেট করুন
  3. অ্যাপ্লিকেশন কোড পরিবর্তন করুন

৩. প্রস্তুতি/পূর্বপ্রস্তুতি

এই বিভাগে ব্যাখ্যা করা হয়েছে কীভাবে:

  1. আপনার ক্লাউড প্রজেক্ট সেট আপ করুন
  2. বেসলাইন নমুনা অ্যাপ পান
  3. বেসলাইন অ্যাপ পুনরায় স্থাপন এবং যাচাই করুন
  4. নতুন গুগল ক্লাউড পরিষেবা/এপিআই সক্রিয় করুন

এই পদক্ষেপগুলো নিশ্চিত করে যে আপনি এমন একটি কার্যকরী কোড দিয়ে শুরু করছেন যা স্বতন্ত্র ক্লাউড পরিষেবাগুলিতে স্থানান্তরের জন্য প্রস্তুত।

১. প্রকল্প স্থাপন করুন

আপনি যদি মডিউল ২০-এর কোডল্যাবটি সম্পন্ন করে থাকেন, তবে সেই একই প্রজেক্ট (এবং কোড) পুনরায় ব্যবহার করুন। বিকল্পভাবে, একটি সম্পূর্ণ নতুন প্রজেক্ট তৈরি করুন অথবা অন্য কোনো বিদ্যমান প্রজেক্ট পুনরায় ব্যবহার করুন। নিশ্চিত করুন যে প্রজেক্টটিতে একটি সক্রিয় বিলিং অ্যাকাউন্ট এবং একটি চালু করা অ্যাপ ইঞ্জিন অ্যাপ রয়েছে। আপনার প্রজেক্ট আইডিটি খুঁজে বের করুন এবং এই কোডল্যাব চলাকালীন এটি হাতের কাছে রাখুন এবং যখনই PROJ_ID ভেরিয়েবলটির সম্মুখীন হবেন, তখন এটি ব্যবহার করুন।

২. বেসলাইন নমুনা অ্যাপটি নিন

পূর্বশর্তগুলোর মধ্যে একটি হলো একটি কার্যকর মডিউল ২০ অ্যাপ ইঞ্জিন অ্যাপ থাকা, তাই হয় এর কোডল্যাবটি সম্পূর্ণ করুন (প্রস্তাবিত; উপরের লিঙ্ক) অথবা রিপো থেকে মডিউল ২০-এর কোড কপি করুন। আপনি আপনারটি বা আমাদেরটি, যা-ই ব্যবহার করুন না কেন, আমরা এখান থেকেই শুরু করব ("START")। এই কোডল্যাবটি আপনাকে মাইগ্রেশনের পুরো প্রক্রিয়াটি ধাপে ধাপে দেখিয়ে দেবে এবং শেষে এমন একটি কোড থাকবে যা মডিউল ২১ রিপো ফোল্ডারের কোডের অনুরূপ ("FINISH")।

মডিউল ২০ রিপো ফোল্ডারটি কপি করুন। এটি দেখতে নিচের আউটপুটের মতো হবে, এবং আপনি যদি মডিউল ২০ কোডল্যাবটি করে থাকেন তবে এতে সম্ভবত একটি lib ফোল্ডারও থাকতে পারে:

$ ls
README.md               appengine_config.py     templates
app.yaml                main.py                 requirements.txt

৩. বেসলাইন অ্যাপ (পুনরায়) স্থাপন এবং যাচাই করুন

মডিউল ২০ অ্যাপটি ডেপ্লয় করতে নিম্নলিখিত ধাপগুলো অনুসরণ করুন:

  1. যদি lib ফোল্ডার থাকে, তবে সেটি মুছে ফেলুন এবং পুনরায় ফাইল তৈরি করতে pip install -t lib -r requirements.txt চালান। আপনার সিস্টেমে Python 2 এবং 3 উভয়ই ইনস্টল করা থাকলে pip2 ব্যবহার করার প্রয়োজন হতে পারে।
  2. আপনি gcloud কমান্ড-লাইন টুলটি ইনস্টলচালু করেছেন এবং এর ব্যবহারবিধি পর্যালোচনা করেছেন কিনা, তা নিশ্চিত করুন।
  3. যদি আপনি প্রতিটি gcloud কমান্ডের সাথে আপনার PROJ_ID প্রবেশ করাতে না চান, তাহলে প্রথমে gcloud config set project PROJ_ID ব্যবহার করে ক্লাউড প্রজেক্টটি সেট করুন।
  4. gcloud app deploy ব্যবহার করে নমুনা অ্যাপটি ডিপ্লয় করুন।
  5. অ্যাপটি কোনো ত্রুটি ছাড়াই প্রত্যাশিতভাবে চলছে কিনা তা নিশ্চিত করুন। আপনি যদি মডিউল ২০-এর কোডল্যাবটি সম্পন্ন করে থাকেন, তাহলে অ্যাপটি ব্যবহারকারীর লগইন তথ্য (ব্যবহারকারীর ইমেল, সম্ভাব্য "অ্যাডমিন ব্যাজ" এবং লগইন/লগআউট বাটন) এবং সাম্প্রতিক ভিজিটগুলো শীর্ষে প্রদর্শন করবে (নিচে চিত্রিত)।

907e64c19ef964f8.png

সাধারণ ব্যবহারকারী হিসেবে সাইন-ইন করলে ব্যবহারকারীর ইমেল ঠিকানা প্রদর্শিত হয় এবং "লগইন" বোতামটি "লগআউট" বোতামে পরিবর্তিত হয়:

ad7b59916b69a035.png

অ্যাডমিন ব্যবহারকারী হিসেবে সাইন-ইন করলে ব্যবহারকারীর ইমেল ঠিকানার পাশে "(অ্যাডমিন)" লেখাটি প্রদর্শিত হয়:

867bcb3334149e4.png

৪. নতুন গুগল ক্লাউড এপিআই/পরিষেবাগুলি সক্রিয় করুন

ভূমিকা

মডিউল ২০ অ্যাপটি অ্যাপ ইঞ্জিন এনডিবি এবং ইউজার্স এপিআই ব্যবহার করে, যা এমন বান্ডেলড পরিষেবা যার জন্য অতিরিক্ত সেটআপের প্রয়োজন হয় না, কিন্তু স্বতন্ত্র ক্লাউড পরিষেবাগুলোর জন্য তা প্রয়োজন। আপডেট করা অ্যাপটি ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম এবং ক্লাউড ডেটাস্টোর উভয়ই ব্যবহার করবে ( ক্লাউড এনডিবি ক্লায়েন্ট লাইব্রেরির মাধ্যমে)। অধিকন্তু, অ্যাপ ইঞ্জিন অ্যাডমিন ব্যবহারকারীদের শনাক্ত করার প্রয়োজনে ক্লাউড রিসোর্স ম্যানেজার এপিআই ব্যবহার করাও আবশ্যক।

খরচ

  • অ্যাপ ইঞ্জিন এবং ক্লাউড ডেটাস্টোরের "সর্বদা বিনামূল্যে" স্তরের কোটা রয়েছে, এবং যতক্ষণ আপনি সেই সীমার মধ্যে থাকবেন, এই টিউটোরিয়ালটি সম্পূর্ণ করতে আপনার কোনো চার্জ লাগার কথা নয়। আরও বিস্তারিত জানতে অ্যাপ ইঞ্জিন প্রাইসিং পেজ এবং ক্লাউড ডেটাস্টোর প্রাইসিং পেজ দেখুন।
  • ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম ব্যবহারের বিল মাসিক সক্রিয় ব্যবহারকারীর (MAU) সংখ্যা বা প্রমাণীকরণ যাচাইকরণের উপর নির্ভর করে ধার্য করা হয়; প্রতিটি ব্যবহারের মডেলের জন্য কোনো না কোনো ধরনের 'ফ্রি' সংস্করণ উপলব্ধ আছে। আরও বিস্তারিত জানতে এর প্রাইসিং পেজ দেখুন। এছাড়াও, যদিও অ্যাপ ইঞ্জিন এবং ক্লাউড ডেটাস্টোরের জন্য বিলিং প্রয়োজন, শুধুমাত্র GCIP ব্যবহারের জন্য বিলিং চালু করার প্রয়োজন হয় না, যতক্ষণ না আপনি এর ইনস্ট্রুমেন্টবিহীন দৈনিক কোটা অতিক্রম করছেন। তাই, যেসব ক্লাউড প্রোজেক্টে বিলিং-এর প্রয়োজন নেই, সেগুলোর জন্য এটি বিবেচনা করতে পারেন।
  • এর প্রাইসিং পেজ অনুসারে, ক্লাউড রিসোর্স ম্যানেজার এপিআই-এর ব্যবহার বেশিরভাগ ক্ষেত্রেই বিনামূল্যে।

ব্যবহারকারীরা তাদের পছন্দ অনুযায়ী ক্লাউড কনসোল থেকে অথবা কমান্ড-লাইন থেকে ( ক্লাউড এসডিকে -এর অংশ gcloud ’ কমান্ডের মাধ্যমে) ক্লাউড এপিআইগুলো সক্রিয় করতে পারেন। চলুন ক্লাউড ডেটাস্টোর এবং ক্লাউড রিসোর্স ম্যানেজার এপিআইগুলো দিয়ে শুরু করা যাক।

ক্লাউড কনসোল থেকে

ক্লাউড কনসোলে (সঠিক প্রজেক্টের জন্য) এপিআই ম্যানেজারের লাইব্রেরি পেজে যান এবং সার্চ বার ব্যবহার করে একটি এপিআই অনুসন্ধান করুন। c7a740304e9d35b.png

এই API-গুলো সক্রিয় করুন:

প্রতিটি API-এর জন্য আলাদাভাবে Enable বাটনটি খুঁজুন এবং ক্লিক করুন—আপনাকে বিলিং তথ্য দিতে বলা হতে পারে। উদাহরণস্বরূপ, এখানে রিসোর্স ম্যানেজার API-এর পেজটি দেওয়া হলো:

fc7bd8f4c49d12e5.png

সক্রিয় হয়ে গেলে (সাধারণত কয়েক সেকেন্ড পর) বাটনটি 'ম্যানেজ'-এ পরিবর্তিত হয়:

8eca12d6cc7b45b0.png

একইভাবে ক্লাউড ডেটাস্টোর সক্রিয় করুন:

83811599b110e46b.png

কমান্ড-লাইন থেকে

কনসোল থেকে এপিআই (API) চালু করাটা দৃশ্যত তথ্যপূর্ণ হলেও, অনেকে কমান্ড-লাইন পছন্দ করেন। এর বাড়তি সুবিধা হলো, আপনি একবারে যেকোনো সংখ্যক এপিআই চালু করতে পারবেন। ক্লাউড ডেটাস্টোর (Cloud Datastore) এবং ক্লাউড রিসোর্স ম্যানেজার (Cloud Resource Manager) উভয় এপিআই চালু করতে এই কমান্ডটি দিন এবং অপারেশনটি সম্পূর্ণ হওয়া পর্যন্ত অপেক্ষা করুন, যেমনটি এখানে দেখানো হয়েছে:

$ gcloud services enable cloudresourcemanager.googleapis.com datastore.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

আপনার কাছে বিলিং তথ্য চাওয়া হতে পারে।

উপরের কমান্ডে ব্যবহৃত প্রতিটি এপিআই-এর "ইউআরএল"-গুলোকে এপিআই সার্ভিস নেম বলা হয়, এবং এগুলো প্রতিটি এপিআই-এর লাইব্রেরি পেজের একেবারে নিচে পাওয়া যায়। আপনি যদি আপনার নিজের অ্যাপের জন্য অন্যান্য ক্লাউড এপিআই সক্রিয় করতে চান, তবে আপনি তাদের নিজ নিজ এপিআই পেজ থেকে তাদের সার্ভিস নেমগুলো খুঁজে নিতে পারেন। এই কমান্ডটি সেইসব এপিআই-এর সমস্ত সার্ভিস নেম তালিকাভুক্ত করে যা আপনি সক্রিয় করতে পারেন:

gcloud services list --available --filter="name:googleapis.com" .

ক্লাউড কনসোলে হোক বা কমান্ড-লাইনে, উপরের ধাপগুলো সম্পন্ন করার পর আমাদের স্যাম্পলটি এখন সেই API-গুলো অ্যাক্সেস করতে সক্ষম হবে। পরবর্তী ধাপগুলো হলো ক্লাউড আইডেন্টিটি প্ল্যাটফর্মটি সক্রিয় করা এবং প্রয়োজনীয় কোড পরিবর্তনগুলো করা।

ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম সক্রিয় এবং সেটআপ করুন (শুধুমাত্র ক্লাউড কনসোল)

ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম একটি মার্কেটপ্লেস পরিষেবা , কারণ এটি গুগল ক্লাউডের বাইরের কোনো রিসোর্সের সাথে সংযুক্ত বা তার উপর নির্ভরশীল, যেমন— ফায়ারবেস অথেনটিকেশন । বর্তমানে, আপনি শুধুমাত্র ক্লাউড কনসোল থেকেই মার্কেটপ্লেস পরিষেবাগুলো সক্রিয় করতে পারবেন। নিচের ধাপগুলো অনুসরণ করুন:

  1. ক্লাউড মার্কেটপ্লেসে ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম পৃষ্ঠায় যান এবং সেখানে থাকা ‘Enable’ বোতামটি ক্লিক করুন। অনুরোধ করা হলে ফায়ারবেস অথেনটিকেশন থেকে আপগ্রেড করুন—এটি করলে অতিরিক্ত ফিচারগুলো আনলক হবে, যেমনটি আগে ব্যাকগ্রাউন্ড বিভাগে বর্ণনা করা হয়েছে। নিচে মার্কেটপ্লেস পৃষ্ঠাটি দেওয়া হলো যেখানে ‘Enable’ বোতামটি হাইলাইট করা আছে: 28475f1c9b29de69.png
  2. আইডেন্টিটি প্ল্যাটফর্ম সক্রিয় করা হলে, আপনাকে স্বয়ংক্রিয়ভাবে আইডেন্টিটি প্রোভাইডার্স পৃষ্ঠায় নিয়ে যাওয়া হতে পারে। তা না হলে, সেখানে যাওয়ার জন্য এই সুবিধাজনক লিঙ্কটি ব্যবহার করুন। fc2d92d42a5d1dd7.png
  3. Google Auth প্রোভাইডারটি সক্রিয় করুন। যদি কোনো প্রোভাইডার সেট আপ করা না থাকে, তাহলে 'Add a Provider'-এ ক্লিক করুন এবং Google নির্বাচন করুন। আপনি যখন এই স্ক্রিনে ফিরে আসবেন, তখন Google এন্ট্রিটি সক্রিয় থাকা উচিত। এই টিউটোরিয়ালে আমরা App Engine Users পরিষেবাটিকে একটি হালকা Google সাইন-ইন পরিষেবা হিসাবে অনুকরণ করার জন্য শুধুমাত্র Google অথ প্রোভাইডারটি ব্যবহার করছি। আপনার নিজের অ্যাপে, আপনি অতিরিক্ত অথ প্রোভাইডার সক্রিয় করতে পারেন।
  4. যখন আপনি গুগল এবং অন্যান্য পছন্দসই অথেন্টিকেশন প্রোভাইডার নির্বাচন ও সেট আপ করে ফেলবেন, তখন 'অ্যাপ্লিকেশন সেটআপ ডিটেইলস'-এ ক্লিক করুন এবং পরবর্তী ডায়ালগ উইন্ডো থেকে, 'ওয়েব' ট্যাবের config অবজেক্টে থাকা apiKey এবং authDomain কপি করে উভয়টিই কোনো নিরাপদ স্থানে সংরক্ষণ করুন। পুরোটা কপি করছেন না কেন? এই ডায়ালগের কোড স্নিপেটটি হার্ডকোডেড এবং পুরনো, তাই শুধু সবচেয়ে গুরুত্বপূর্ণ অংশগুলো সংরক্ষণ করুন এবং পরবর্তীতে যখন ফায়ারবেস অথেন্টিকেশন একসাথে বেশি ব্যবহৃত হবে, তখন আমাদের কোডে সেগুলো ব্যবহার করুন। ভ্যালুগুলো কপি করে কোনো নিরাপদ স্থানে সংরক্ষণ করার পর, 'ক্লোজ' বোতামে ক্লিক করুন, যার মাধ্যমে সমস্ত প্রয়োজনীয় সেটআপ সম্পন্ন হবে। bbb09dcdd9be538e.png

৪. কনফিগারেশন আপডেট করুন

কনফিগারেশন আপডেটের মধ্যে বিভিন্ন কনফিগারেশন ফাইল পরিবর্তন করার পাশাপাশি ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম ইকোসিস্টেমের মধ্যে অ্যাপ ইঞ্জিনের সমতুল্য কিছু তৈরি করাও অন্তর্ভুক্ত।

appengine_config.py

  • পাইথন ৩-এ আপগ্রেড করলে appengine_config.py মুছে ফেলুন।
  • আইডেন্টিটি প্ল্যাটফর্মে আধুনিকীকরণের পরিকল্পনা থাকলেও যদি পাইথন ২ ব্যবহার করতে চান , তবে ফাইলটি ডিলিট করবেন না। পরিবর্তে, আমরা পরবর্তীতে পাইথন ২ ব্যাকপোর্টের সময় এটি আপডেট করব।

requirements.txt

মডিউল ২০-এর requirements.txt ফাইলে শুধুমাত্র Flask তালিকাভুক্ত ছিল। মডিউল ২১-এর জন্য, নিম্নলিখিত প্যাকেজগুলো যোগ করুন:

requirements.txt ফাইলের বিষয়বস্তু এখন দেখতে এইরকম হবে:

flask
google-auth
google-cloud-ndb
google-cloud-resource-manager
firebase-admin

app.yaml

  • পাইথন ৩-এ আপগ্রেড করার অর্থ হলো app.yaml ফাইলটিকে সরল করা। `runtime` ডিরেক্টিভটি ছাড়া বাকি সবকিছু মুছে ফেলুন এবং সেটিকে পাইথন ৩-এর বর্তমানে সমর্থিত কোনো সংস্করণে সেট করুন। উদাহরণটিতে বর্তমানে সংস্করণ ৩.১০ ব্যবহার করা হয়েছে।
  • আপনি যদি পাইথন ২ ব্যবহার করতে থাকেন, তবে আপাতত এখানে কোনো পদক্ষেপ নেবেন না।

পূর্বে:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

মডিউল ২০-এর স্যাম্পল অ্যাপটিতে কোনো স্ট্যাটিক ফাইল হ্যান্ডলার নেই। যদি আপনার অ্যাপে থাকে, তবে সেগুলোকে অপরিবর্তিত রাখুন। আপনি চাইলে আপনার সমস্ত স্ক্রিপ্ট হ্যান্ডলার মুছে ফেলতে পারেন, অথবা শুধু রেফারেন্সের জন্য রেখে দিতে পারেন, তবে শর্ত হলো আপনাকে app.yaml মাইগ্রেশন গাইডে বর্ণিত পদ্ধতি অনুযায়ী সেগুলোর হ্যান্ডেল ' auto তে পরিবর্তন করতে হবে। এই পরিবর্তনগুলোর ফলে, পাইথন ৩-এর জন্য আপডেট করা app.yaml ফাইলটি সরলীকৃত হয়ে দাঁড়ায়:

পরে:

runtime: python310

অন্যান্য কনফিগারেশন আপডেট

পাইথন ২ ব্যবহার করুন বা পাইথন ৩-এ পোর্ট করুন, আপনার যদি একটি lib ফোল্ডার থাকে, তবে সেটি মুছে ফেলুন।

৫. অ্যাপ্লিকেশন কোড পরিবর্তন করুন

এই বিভাগে মূল অ্যাপ্লিকেশন ফাইল, main.py তে আপডেট আনা হয়েছে, যেখানে App Engine Users সার্ভিসের পরিবর্তে Cloud Identity Platform ব্যবহার করা হয়েছে। মূল অ্যাপ্লিকেশনটি আপডেট করার পর, আপনাকে ওয়েব টেমপ্লেট, templates/index.html আপডেট করতে হবে।

আমদানি এবং প্রারম্ভিকীকরণ আপডেট করুন

ইম্পোর্ট আপডেট করতে এবং অ্যাপ্লিকেশন রিসোর্স ইনিশিয়ালাইজ করতে নিচের ধাপগুলো অনুসরণ করুন:

  1. ইম্পোর্ট করার ক্ষেত্রে, অ্যাপ ইঞ্জিন এনডিবি (App Engine NDB)-কে ক্লাউড এনডিবি (Cloud NDB) দিয়ে প্রতিস্থাপন করুন।
  2. ক্লাউড এনডিবি-র পাশাপাশি ক্লাউড রিসোর্স ম্যানেজারও ইম্পোর্ট করুন।
  3. আইডেন্টিটি প্ল্যাটফর্মটি ফায়ারবেস অথেন্টিকেশন (Firebase Auth) ভিত্তিক, তাই ফায়ারবেস অ্যাডমিন এসডিকে (Firebase Admin SDK) ইম্পোর্ট করুন।
  4. ক্লাউড এপিআই ব্যবহারের জন্য একটি এপিআই ক্লায়েন্ট প্রয়োজন, তাই ফ্লাস্ক ইনিশিয়ালাইজ করার ঠিক নিচে ক্লাউড এনডিবি-র জন্য এটি চালু করুন।

যদিও এখানে ক্লাউড রিসোর্স ম্যানেজার প্যাকেজটি ইম্পোর্ট করা হয়েছে, আমরা অ্যাপ ইনিশিয়ালাইজেশনের পরবর্তী পর্যায়ে এটি ব্যবহার করব। নিচে মডিউল ২০-এর ইম্পোর্ট এবং ইনিশিয়ালাইজেশন দেওয়া হলো এবং এরপরে উপরের পরিবর্তনগুলি বাস্তবায়নের পরে বিভাগগুলি কেমন দেখাবে তা দেখানো হলো:

পূর্বে:

from flask import Flask, render_template, request
from google.appengine.api import users
from google.appengine.ext import ndb

app = Flask(__name__)

পরে:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

# initialize Flask and Cloud NDB API client
app = Flask(__name__)
ds_client = ndb.Client()

অ্যাপ ইঞ্জিন অ্যাডমিন ব্যবহারকারীদের জন্য সহায়তা

অ্যাডমিন ব্যবহারকারীদের শনাক্তকরণ সমর্থন করে এমন দুটি উপাদান অ্যাপটিতে যোগ করতে হবে:

  • _get_gae_admins() — অ্যাডমিন ব্যবহারকারীদের সেট সংগ্রহ করে; একবার কল করা হয় এবং সংরক্ষিত থাকে।
  • is_admin() — সাইন-ইন করা ব্যবহারকারী অ্যাডমিন ব্যবহারকারী কিনা তা পরীক্ষা করে; যেকোনো ব্যবহারকারী লগইন করার সময় এটি কল করা হয়।

_get_gae_admins() ইউটিলিটি ফাংশনটি বর্তমান ক্লাউড IAM allow-policy আনার জন্য রিসোর্স ম্যানেজার API-কে কল করে। এই allow-policy নির্ধারণ করে এবং প্রয়োগ করে যে কোন প্রিন্সিপালদের (সাধারণ ব্যবহারকারী, সার্ভিস অ্যাকাউন্ট, ইত্যাদি) কোন ভূমিকা (roles) প্রদান করা হবে। সেটআপের মধ্যে রয়েছে:

  • ক্লাউড প্রজেক্ট আইডি ( PROJ_ID ) সংগ্রহ করা হচ্ছে
  • রিসোর্স ম্যানেজার এপিআই ক্লায়েন্ট ( rm_client ) তৈরি করা
  • অ্যাপ ইঞ্জিন অ্যাডমিন রোলের একটি (শুধুমাত্র পঠনযোগ্য) সেট তৈরি করা ( _TARGETS )

রিসোর্স ম্যানেজারের জন্য ক্লাউড প্রজেক্ট আইডি প্রয়োজন, তাই google.auth.default() ইম্পোর্ট করুন এবং প্রজেক্ট আইডি পেতে সেই ফাংশনটি কল করুন। এই কলে একটি প্যারামিটার থাকে যা দেখতে একটি URL-এর মতো হলেও এটি একটি OAuth2 পারমিশন স্কোপ । ক্লাউডে অ্যাপ চালানোর সময়, যেমন একটি Compute Engine VM বা App Engine অ্যাপে, একটি ডিফল্ট সার্ভিস অ্যাকাউন্ট দেওয়া হয় যার ব্যাপক প্রিভিলেজ থাকে। সর্বনিম্ন প্রিভিলেজের সর্বোত্তম অনুশীলন মেনে চলার জন্য, আমরা আপনার নিজস্ব ইউজার-ম্যানেজড সার্ভিস অ্যাকাউন্ট তৈরি করার পরামর্শ দিই।

এপিআই কলের ক্ষেত্রে, সঠিকভাবে কাজ করার জন্য প্রয়োজনীয় ন্যূনতম স্তরে আপনার অ্যাপের স্কোপ আরও কমিয়ে আনা সর্বোত্তম। আমরা যে রিসোর্স ম্যানেজার এপিআই কলটি করব তা হলো get_iam_policy() , যা কাজ করার জন্য নিম্নলিখিত স্কোপগুলির মধ্যে একটির প্রয়োজন :

  • https://www.googleapis.com/auth/cloud-platform
  • https://www.googleapis.com/auth/cloud-platform.read-only
  • https://www.googleapis.com/auth/cloudplatformprojects
  • https://www.googleapis.com/auth/cloudplatformprojects.readonly

স্যাম্পল অ্যাপটির জন্য allow-policy-তে শুধুমাত্র রিড-অনলি অ্যাক্সেস প্রয়োজন। এটি পলিসিটি পরিবর্তন করে না, বা পুরো প্রজেক্টে অ্যাক্সেসেরও প্রয়োজন নেই। এর মানে হলো, অ্যাপটির জন্য প্রয়োজনীয় প্রথম তিনটি পারমিশনের কোনোটিরই দরকার নেই। শুধুমাত্র শেষেরটিই প্রয়োজন, এবং স্যাম্পল অ্যাপটির জন্য আমরা সেটিই ইমপ্লিমেন্ট করছি।

ফাংশনের মূল অংশে অ্যাডমিন ব্যবহারকারীদের ( admins ) একটি খালি সেট তৈরি করা হয়, get_iam_policy() এর মাধ্যমে allow_policy সংগ্রহ করা হয়, এবং বিশেষভাবে App Engine Admin রোলগুলো খোঁজার জন্য এর সমস্ত বাইন্ডিংয়ের মধ্যে লুপ চালানো হয়:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin

খুঁজে পাওয়া প্রতিটি টার্গেট রোলের জন্য, এটি সেই রোলের অন্তর্ভুক্ত ব্যবহারকারীদের একত্রিত করে এবং তাদের অ্যাডমিন ব্যবহারকারীদের সামগ্রিক সেটে যুক্ত করে। সবশেষে, এটি খুঁজে পাওয়া সমস্ত অ্যাডমিন ব্যবহারকারীকে এই অ্যাপ ইঞ্জিন ইনস্ট্যান্সটির জীবনকাল পর্যন্ত একটি কনস্ট্যান্ট ( _ADMINS ) হিসেবে রিটার্ন করে ও ক্যাশ করে রাখে। আমরা শীঘ্রই সেই কলটি দেখতে পাব।

cloud NDB API ক্লায়েন্ট ( ds_client ) ইনস্ট্যানশিয়েট করার ঠিক নিচে main.py ফাইলে নিম্নলিখিত _get_gae_admins() ফাংশন সংজ্ঞাটি যোগ করুন:

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    _, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
    rm_client = resourcemanager.ProjectsClient()
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
    for b in allow_policy.bindings:     # bindings in IAM allow-policy
        if b.role in _TARGETS:          # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b.members)
    return admins

যখন ব্যবহারকারীরা অ্যাপে লগইন করেন, তখন নিম্নলিখিত ঘটনাগুলো ঘটে:

  1. কোনো ব্যবহারকারী ফায়ারবেসে সাইন ইন করার পর ওয়েব টেমপ্লেট থেকে দ্রুত একটি যাচাই করা হয়।
  2. টেমপ্লেটে অথোরাইজেশন স্টেট পরিবর্তিত হলে, /is_admin এ একটি Ajax-স্টাইলের fetch() কল করা হয়, যার হ্যান্ডলার হলো পরবর্তী ফাংশন, is_admin()
  3. Firebase ID Token-টি POST বডিতে is_admin() পাঠানো হয়, যা হেডার থেকে টোকেনটি সংগ্রহ করে এবং যাচাই করার জন্য Firebase Admin SDK-কে কল করে। যদি ব্যবহারকারীটি বৈধ হয়, তবে তার ইমেল ঠিকানা বের করে নেওয়া হয় এবং তিনি অ্যাডমিন ব্যবহারকারী কিনা তা যাচাই করা হয়।
  4. এরপর বুলিয়ান ফলাফলটি একটি সফল ২০০ হিসেবে টেমপ্লেটে ফেরত পাঠানো হয়।

main.py ফাইলে _get_gae_admins() ) এর ঠিক পরেই is_admin() যোগ করুন:

@app.route('/is_admin', methods=['POST'])
def is_admin():
    'check if user (via their Firebase ID token) is GAE admin (POST) handler'
    id_token = request.headers.get('Authorization')
    email = auth.verify_id_token(id_token).get('email')
    return {'admin': email in _ADMINS}, 200

Users সার্ভিসে উপলব্ধ কার্যকারিতা, বিশেষ করে এর is_current_user_admin() ফাংশনটির কার্যকারিতা প্রতিলিপি করার জন্য উভয় ফাংশনের সমস্ত কোডের প্রয়োজন। মডিউল ২০-এর এই ফাংশন কলটিই সমস্ত কঠিন কাজটি করেছে, যা মডিউল ২১-এর থেকে ভিন্ন, যেখানে আমরা একটি বিকল্প সমাধান প্রয়োগ করেছি। সুখবর হলো, অ্যাপটি এখন আর শুধুমাত্র App Engine-ভিত্তিক কোনো সার্ভিসের উপর নির্ভরশীল নয়, যার অর্থ হলো আপনি আপনার অ্যাপগুলোকে Cloud Run বা অন্যান্য সার্ভিসে স্থানান্তর করতে পারবেন। এছাড়াও, আপনি _TARGETS এ কাঙ্ক্ষিত রোলগুলোতে পরিবর্তন করে আপনার নিজের অ্যাপের জন্য "অ্যাডমিন ইউজার"-এর সংজ্ঞা পরিবর্তন করতে পারবেন, যেখানে Users সার্ভিসটি App Engine অ্যাডমিন রোলগুলোর জন্য হার্ডকোড করা থাকে।

ফায়ারবেস অথেন্টিকেশন শুরু করুন এবং অ্যাপ ইঞ্জিন অ্যাডমিন ব্যবহারকারীদের ক্যাশে করুন

আমরা চাইলে একদম উপরে, যেখানে ফ্লাস্ক অ্যাপ ইনিশিয়ালাইজ করা হয় এবং ক্লাউড এনডিবি এপিআই ক্লায়েন্ট তৈরি করা হয়, তার কাছাকাছিই ফায়ারবেস অথেন্টিকেশন ইনিশিয়ালাইজ করতে পারতাম, কিন্তু সমস্ত অ্যাডমিন কোড সংজ্ঞায়িত না হওয়া পর্যন্ত এর কোনো প্রয়োজন ছিল না, এবং আমরা এখন সেই পর্যায়েই আছি। একইভাবে, এখন যেহেতু _get_gae_admins() সংজ্ঞায়িত করা হয়েছে, অ্যাডমিন ব্যবহারকারীদের তালিকা ক্যাশ করার জন্য এটিকে কল করুন।

is_admin() ফাংশনের বডির ঠিক নিচে এই লাইনগুলো যোগ করুন:

# initialize Firebase and fetch set of App Engine admins
initialize_app()
_ADMINS = _get_gae_admins()

ডেটা মডেল আপডেট পরিদর্শন করুন

Visit ডেটা মডেল অপরিবর্তিত থাকে। ডেটাস্টোর অ্যাক্সেসের জন্য ক্লাউড এনডিবি এপিআই ক্লায়েন্ট কনটেক্সট ম্যানেজার, ds_client.context() -এর সুস্পষ্ট ব্যবহার প্রয়োজন। কোডের ক্ষেত্রে, এর অর্থ হলো store_visit() এবং fetch_visits() উভয় ডেটাস্টোর কলকে পাইথনের with ব্লকের মধ্যে রাখতে হবে। এই আপডেটটি মডিউল ২-এর অনুরূপ। নিম্নলিখিত পরিবর্তনগুলো করুন:

পূর্বে:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

পরে:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

ব্যবহারকারীর লগইন লজিক ওয়েব টেমপ্লেটে স্থানান্তর করুন

অ্যাপ ইঞ্জিন ইউজার্স সার্ভিসটি সার্ভার-সাইড, অপরদিকে ফায়ারবেস অথ এবং ক্লাউড আইডেন্টিটি প্ল্যাটফর্ম প্রধানত ক্লায়েন্ট-সাইড। ফলে, মডিউল ২০ অ্যাপের ইউজার ম্যানেজমেন্ট কোডের একটি বড় অংশ মডিউল ২১ ওয়েব টেমপ্লেটে স্থানান্তরিত হয়।

main.py ফাইলে, ওয়েব কনটেক্সট টেমপ্লেটে পাঁচটি অপরিহার্য ডেটা প্রেরণ করে, যার মধ্যে প্রথম চারটি ব্যবহারকারী ব্যবস্থাপনার সাথে সম্পর্কিত এবং ব্যবহারকারী সাইন-ইন করা আছে কি না তার উপর নির্ভর করে এগুলি ভিন্ন হয়:

  • who — ব্যবহারকারীর ইমেল, যদি সাইন-ইন করা থাকে, অথবা অন্যথায় ব্যবহারকারী।
  • admin(অ্যাডমিন) ব্যাজ, যদি সাইন-ইন করা ব্যবহারকারী একজন অ্যাডমিন হন।
  • signলগইন বা লগআউট বোতাম দেখান
  • বাটন ক্লিকে link -ইন বা সাইন-আউট লিঙ্ক
  • visits — সাম্প্রতিকতম পরিদর্শন

পূর্বে:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)

    # put together users context for web template
    user = users.get_current_user()
    context = {  # logged in
        'who':   user.nickname(),
        'admin': '(admin)' if users.is_current_user_admin() else '',
        'sign':  'Logout',
        'link':  '/_ah/logout?continue=%s://%s/' % (
                      request.environ['wsgi.url_scheme'],
                      request.environ['HTTP_HOST'],
                  ),  # alternative to users.create_logout_url()
    } if user else {  # not logged in
        'who':   'user',
        'admin': '',
        'sign':  'Login',
        'link':  users.create_login_url('/'),
    }

    # add visits to context and render template
    context['visits'] = visits  # display whether logged in or not
    return render_template('index.html', **context)

ব্যবহারকারী ব্যবস্থাপনার সবকিছু ওয়েব টেমপ্লেটে স্থানান্তরিত হচ্ছে, ফলে আমাদের কাছে শুধু ভিজিটগুলোই থাকছে এবং মূল হ্যান্ডলারটি আমরা মডিউল ১ অ্যাপের অবস্থায় ফিরিয়ে আনছি:

পরে:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

ওয়েব টেমপ্লেট আপডেট করুন

টেমপ্লেটে আগের অংশের সমস্ত আপডেটগুলো কেমন দেখাচ্ছে? প্রধানত, ইউজার ম্যানেজমেন্টকে অ্যাপ থেকে সরিয়ে টেমপ্লেটে চলমান Firebase Auth-এ আনা হয়েছে এবং জাভাস্ক্রিপ্টে স্থানান্তরিত করা সমস্ত কোডের একটি আংশিক পোর্ট করা হয়েছে। আমরা দেখেছি main.py আকার বেশ কিছুটা ছোট হয়েছে, তাই templates/index.html এও একই রকম বৃদ্ধি আশা করা যায়।

পূর্বে:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
</head>
<body>
<p>
Welcome, {{ who }} <code>{{ admin }}</code>
<button id="logbtn">{{ sign }}</button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
document.getElementById("logbtn").onclick = () => {
    window.location.href = '{{ link }}';
};
</script>
</body>
</html>

সম্পূর্ণ ওয়েব টেমপ্লেটটি নিচের বিষয়বস্তু দিয়ে প্রতিস্থাপন করুন:

পরে:

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

এই HTML বডিতে অনেকগুলো উপাদান রয়েছে, তাই চলুন এক এক করে সেগুলো দেখি।

ফায়ারবেস আমদানি

এইচটিএমএল ডকুমেন্টের হেডারেই, পেজ টাইটেল পার হওয়ার পর, প্রয়োজনীয় ফায়ারবেস কম্পোনেন্টগুলো ইম্পোর্ট করুন। কার্যকারিতার জন্য ফায়ারবেস কম্পোনেন্টগুলোকে এখন একাধিক মডিউলে ভাগ করা হয়েছে। ফায়ারবেস ইনিশিয়ালাইজ করার কোড মূল ফায়ারবেস অ্যাপ মডিউল থেকে ইম্পোর্ট করা হয়, অন্যদিকে ফায়ারবেস অথেন্টিকেশন, অথেন্টিকেশন প্রোভাইডার হিসেবে গুগল, সাইন ইন ও আউট এবং অথেন্টিকেশন স্টেট পরিবর্তনের 'কলব্যাক' পরিচালনা করার ফাংশনগুলো ফায়ারবেস অথ মডিউল থেকে ইম্পোর্ট করা হয়।

<!doctype html>
<html>
<head>
<title>VisitMe Example</title>

<script type="module">
// import Firebase module attributes
import {
        initializeApp
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import {
        GoogleAuthProvider,
        getAuth,
        onAuthStateChanged,
        signInWithPopup,
        signOut
} from "https://www.gstatic.com/firebasejs/9.10.0/firebase-auth.js";

ফায়ারবেস কনফিগারেশন

এই টিউটোরিয়ালের আইডেন্টিটি প্ল্যাটফর্ম সেটআপ অংশের শুরুতে, আপনি অ্যাপ্লিকেশন সেটআপ ডিটেইলস ডায়ালগ থেকে apiKey এবং authDomain সেভ করেছিলেন। পরবর্তী অংশে, সেই মানগুলো firebaseConfig ভেরিয়েবলে যোগ করুন। আরও বিস্তারিত নির্দেশাবলীর জন্য একটি লিঙ্ক কমেন্টে দেওয়া আছে:

// Firebase config:
// 1a. Go to: console.cloud.google.com/customer-identity/providers
// 1b. May be prompted to enable GCIP and upgrade from Firebase
// 2. Click: "Application Setup Details" button
// 3. Copy: 'apiKey' and 'authDomain' from 'config' variable
var firebaseConfig = {
        apiKey: "YOUR_API_KEY",
        authDomain: "YOUR_AUTH_DOMAIN",
};

ফায়ারবেস প্রারম্ভিককরণ

পরবর্তী অংশটি এই কনফিগারেশন তথ্য দিয়ে ফায়ারবেস চালু করে।

// initialize Firebase app & auth components
initializeApp(firebaseConfig);
var auth = getAuth();
var provider = new GoogleAuthProvider();
//provider.setCustomParameters({prompt: 'select_account'});

এটি গুগলকে অথেন্টিকেশন প্রোভাইডার হিসেবে ব্যবহার করার সুবিধা দেয় এবং আপনার ব্রাউজার সেশনে একটিমাত্র গুগল অ্যাকাউন্ট রেজিস্টার করা থাকলেও অ্যাকাউন্ট সিলেক্টরটি দেখানোর জন্য একটি কমেন্ট-আউট করা অপশন প্রদান করে। অন্য কথায়, যখন আপনার একাধিক অ্যাকাউন্ট থাকে, তখন প্রত্যাশা অনুযায়ী আপনাকে এই "অ্যাকাউন্ট-পিকার"টি দেখানো হয়: a38369389b7c4c7e.png তবে, সেশনে যদি কেবল একজন ব্যবহারকারী থাকেন, তাহলে ব্যবহারকারীর কোনো হস্তক্ষেপ ছাড়াই লগইন প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে সম্পন্ন হয়। (পপআপটি দেখা যায় এবং তারপর অদৃশ্য হয়ে যায়।) আপনি কাস্টম প্যারামিটার লাইনটি আনকমেন্ট করে একজন ব্যবহারকারীর জন্য অ্যাকাউন্ট-পিকার ডায়ালগটি দেখাতে বাধ্য করতে পারেন (অ্যাপে অবিলম্বে লগইন করার পরিবর্তে)। এটি সক্রিয় করা থাকলে, একক-ব্যবহারকারীর লগইনের ক্ষেত্রেও অ্যাকাউন্ট-পিকারটি প্রদর্শিত হয়: b75624cb68d94557.png

লগইন এবং লগআউট ফাংশন

পরবর্তী কোড লাইনগুলো লগইন বা লগআউট বাটনে ক্লিকের জন্য ফাংশনগুলো তৈরি করে:

// define login and logout button functions
function login() {
    signInWithPopup(auth, provider);
};

function logout() {
    signOut(auth);
};

সাইন-ইন এবং সাইন-আউট কার্যক্রম

এই <script> ব্লকের শেষ প্রধান অংশটি হলো সেই ফাংশন, যা প্রতিটি প্রমাণীকরণ পরিবর্তনের (সাইন-ইন বা সাইন-আউট) জন্য কল করা হয়।

// check if admin & switch to logout button on login; reset everything on logout
onAuthStateChanged(auth, async (user) => {
    if (user && user != null) {
        var email = user.email;
        who.innerHTML = email;
        logbtn.onclick = logout;
        logbtn.innerHTML = "Logout";
        var idToken = await user.getIdToken();
        var rsp = await fetch("/is_admin", {
                method: "POST",
                headers: {Authorization: idToken}
        });
        var data = await rsp.json();
        if (data.admin) {
            admin.style.display = "inline";
        }
    } else {
        who.innerHTML = "user";
        admin.style.display = "none";
        logbtn.onclick = login;
        logbtn.innerHTML = "Login";
    }
});
</script>
</head>

মডিউল ২০-এর যে কোডটি 'ব্যবহারকারী লগ ইন করেছেন' টেমপ্লেট কনটেক্সট নাকি 'ব্যবহারকারী লগ আউট করেছেন' কনটেক্সট পাঠানো হবে তা নির্ধারণ করে, সেটি এখানে স্থানান্তরিত করা হয়েছে। উপরের শর্তটি ' true হয় যদি ব্যবহারকারী সফলভাবে লগ ইন করেন, যা নিম্নলিখিত অ্যাকশনগুলো ট্রিগার করে:

  1. ব্যবহারকারীর ইমেল ঠিকানাটি প্রদর্শনের জন্য সেট করা হয়েছে।
  2. লগইন বাটনটি লগআউটে পরিবর্তিত হয়ে যায়।
  3. (admin) অ্যাডমিন ব্যবহারকারীর ব্যাজটি দেখানো হবে কিনা তা নির্ধারণ করতে /is_admin এ একটি Ajax-স্টাইলের কল করা হয়।

যখন ব্যবহারকারী লগ আউট করেন, তখন ব্যবহারকারীর সমস্ত তথ্য রিসেট করার জন্য else ক্লজটি কার্যকর হয়:

  1. ব্যবহারকারীর নাম ব্যবহারকারীকে সেট করা হয়েছে
  2. যেকোনো অ্যাডমিন ব্যাজ মুছে ফেলা হয়েছে
  3. লগআউট বাটনটি আবার লগইন- এ পরিবর্তন করা হয়েছে

টেমপ্লেট ভেরিয়েবল

হেডার সেকশন শেষ হওয়ার পর মূল অংশ শুরু হয় টেমপ্লেট ভেরিয়েবলগুলো দিয়ে, যেগুলো প্রয়োজন অনুযায়ী পরিবর্তিত হওয়া HTML এলিমেন্ট দ্বারা প্রতিস্থাপিত হয়:

  1. প্রদর্শিত ব্যবহারকারীর নাম
  2. (admin) অ্যাডমিন ব্যাজ (প্রযোজ্য হলে)
  3. লগইন বা লগআউট বোতাম
<body>
<p>
Welcome, <span id="who"></span> <span id="admin"><code>(admin)</code></span>
<button id="logbtn"></button>
</p><hr>

সাম্প্রতিকতম পরিদর্শন এবং HTML এলিমেন্ট ভেরিয়েবল

সর্বশেষ ভিজিটের কোড অপরিবর্তিত থাকে, এবং শেষের <script> ব্লকটি ঠিক উপরে তালিকাভুক্ত সাইন-ইন এবং সাইন-আউটের জন্য পরিবর্তিত হওয়া HTML এলিমেন্টগুলোর ভ্যারিয়েবল সেট করে:

<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
    <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>

<script>
var who    = document.getElementById("who");
var admin  = document.getElementById("admin");
var logbtn = document.getElementById("logbtn");
</script>
</body>
</html>

অ্যাপ ইঞ্জিন এনডিবি ও ইউজার্স এপিআই থেকে ক্লাউড এনডিবি ও আইডেন্টিটি প্ল্যাটফর্মে পরিবর্তন এবং পাইথন ৩-এ আপগ্রেড করার জন্য অ্যাপ্লিকেশন ও ওয়েব টেমপ্লেটে প্রয়োজনীয় পরিবর্তনগুলো এখানেই শেষ হলো। আপনার নতুন মডিউল ২১ স্যাম্পল অ্যাপটি তৈরি করার জন্য অভিনন্দন! আমাদের সংস্করণটি মডিউল ২১বি রিপো ফোল্ডারে পর্যালোচনার জন্য উপলব্ধ আছে।

কোডল্যাবের পরবর্তী অংশটি ঐচ্ছিক (*) এবং শুধুমাত্র সেইসব ব্যবহারকারীদের জন্য যাদের অ্যাপ অবশ্যই পাইথন ২-এ রাখতে হবে। এটি আপনাকে একটি কার্যকরী পাইথন ২ মডিউল ২১ অ্যাপ তৈরি করার জন্য প্রয়োজনীয় ধাপগুলোর মধ্য দিয়ে নিয়ে যাবে।

৬. *পাইথন ২ ব্যাকপোর্ট

এই ঐচ্ছিক অংশটি সেইসব ডেভেলপারদের জন্য, যারা আইডেন্টিটি প্ল্যাটফর্ম মাইগ্রেশন করছেন কিন্তু পাইথন ২ রানটাইমে কাজ চালিয়ে যেতে বাধ্য। যদি এটি আপনার জন্য কোনো উদ্বেগের বিষয় না হয়, তবে এই অংশটি এড়িয়ে যান।

মডিউল ২১ অ্যাপটির একটি কার্যকর পাইথন ২ সংস্করণ তৈরি করতে আপনার নিম্নলিখিত জিনিসগুলির প্রয়োজন হবে:

  1. রানটাইম প্রয়োজনীয়তা : পাইথন ২ সমর্থনকারী কনফিগারেশন ফাইল, এবং পাইথন ৩-এর অসঙ্গতি এড়ানোর জন্য মূল অ্যাপ্লিকেশনে প্রয়োজনীয় পরিবর্তন।
  2. লাইব্রেরিতে সামান্য পরিবর্তন: রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরিতে কিছু প্রয়োজনীয় ফিচার যোগ করার আগেই পাইথন ২-কে অপ্রচলিত ঘোষণা করা হয়েছিল। ফলে, সেই অনুপস্থিত কার্যকারিতা অ্যাক্সেস করার জন্য আপনার একটি বিকল্প উপায় প্রয়োজন।

চলুন এখন কনফিগারেশন দিয়ে শুরু করে সেই পদক্ষেপগুলো নেওয়া যাক।

appengine_config.py পুনরুদ্ধার করুন

এই টিউটোরিয়ালের শুরুতে আপনাকে appengine_config.py ডিলিট করতে বলা হয়েছিল, কারণ পাইথন ৩ অ্যাপ ইঞ্জিন রানটাইম এটি ব্যবহার করে না। পাইথন ২-এর ক্ষেত্রে, শুধু এটি সংরক্ষণ করলেই হবে না, বরং মডিউল ২০-এর appengine_config.py ফাইলটিকেও আপডেট করতে হবে, যাতে এটি বিল্ট-ইন থার্ড-পার্টি লাইব্রেরি , যেমন grpcio এবং setuptools , ব্যবহারের সুবিধা দেয়। যখনই আপনার অ্যাপ ইঞ্জিন অ্যাপ ক্লাউড এনডিবি এবং ক্লাউড রিসোর্স ম্যানেজারের মতো ক্লাউড ক্লায়েন্ট লাইব্রেরি ব্যবহার করে, তখনই এই প্যাকেজগুলো প্রয়োজন হয়।

আপনি কিছুক্ষণের মধ্যেই ওই প্যাকেজগুলো app.yaml এ যোগ করবেন, কিন্তু আপনার অ্যাপের সেগুলোতে অ্যাক্সেস পাওয়ার জন্য setuptools থেকে pkg_resources.working_set.add_entry() ফাংশনটি অবশ্যই কল করতে হবে। এর ফলে lib ফোল্ডারে ইনস্টল করা কপি করা (সেলফ-বান্ডেলড বা ভেন্ডরড) থার্ড-পার্টি লাইব্রেরিগুলো বিল্ট-ইন লাইব্রেরিগুলোর সাথে যোগাযোগ করতে পারে।

এই পরিবর্তনগুলি কার্যকর করতে আপনার appengine_config.py ফাইলে নিম্নলিখিত আপডেটগুলি প্রয়োগ করুন:

পূর্বে:

from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)

শুধুমাত্র এই কোডটি setuptools এবং grpcio ব্যবহারের জন্য যথেষ্ট নয়। আরও কয়েকটি লাইন প্রয়োজন, তাই appengine_config.py আপডেট করে এইরকম করুন:

পরে:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

ক্লাউড ক্লায়েন্ট লাইব্রেরি সমর্থন করার জন্য প্রয়োজনীয় পরিবর্তনগুলির বিষয়ে আরও বিশদ বিবরণ বান্ডেল পরিষেবা স্থানান্তরের ডকুমেন্টেশনে পাওয়া যাবে।

app.yaml

appengine_config.py এর মতোই, app.yaml ফাইলটিকেও পাইথন ২ সমর্থন করে এমন একটি ফাইলে ফিরিয়ে আনতে হবে। চলুন মূল মডিউল ২০-এর app.yaml দিয়ে শুরু করা যাক:

পূর্বে:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

পূর্বে উল্লিখিত setuptools এবং grpcio ছাড়াও, একটি নির্ভরতা (যা আইডেন্টিটি প্ল্যাটফর্ম মাইগ্রেশনের সাথে সরাসরি সম্পর্কিত নয়) রয়েছে যার জন্য ক্লাউড স্টোরেজ ক্লায়েন্ট লাইব্রেরি ব্যবহার করা প্রয়োজন, এবং এর জন্য আরেকটি বিল্ট-ইন থার্ড-পার্টি প্যাকেজ, ssl , দরকার। app.yaml এর একটি নতুন libraries বিভাগে এই তিনটিই যোগ করুন এবং প্যাকেজগুলোর "সর্বশেষ" উপলব্ধ সংস্করণগুলো নির্বাচন করুন:

পরে:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

requirements.txt

মডিউল ২১-এর জন্য, আমরা Python 3 requirements.txt ফাইলে Google Auth , Cloud NDB , Cloud Resource Manager এবং Firebase Admin SDK যোগ করেছি। Python 2-এর ক্ষেত্রে পরিস্থিতি আরও জটিল:

  • রিসোর্স ম্যানেজার এপিআই নমুনা অ্যাপটির জন্য প্রয়োজনীয় allow-policy কার্যকারিতা প্রদান করে। দুর্ভাগ্যবশত, ক্লাউড রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরির চূড়ান্ত পাইথন ২ সংস্করণে এই সমর্থনটি তখনও উপলব্ধ ছিল না। (এটি শুধুমাত্র পাইথন ৩ সংস্করণে উপলব্ধ।)
  • ফলস্বরূপ, এপিআই থেকে এই ফিচারটি অ্যাক্সেস করার জন্য একটি বিকল্প পদ্ধতির প্রয়োজন। এর সমাধান হলো এপিআই-এর সাথে যোগাযোগের জন্য নিম্ন-স্তরের গুগল এপিআই ক্লায়েন্ট লাইব্রেরি ব্যবহার করা। এই ক্লায়েন্ট লাইব্রেরিতে স্যুইচ করতে, google-cloud-resource-manager নিম্ন-স্তরের google-api-python-client প্যাকেজ দিয়ে প্রতিস্থাপন করুন।
  • যেহেতু পাইথন ২-এর ব্যবহার বন্ধ হয়ে গেছে , তাই মডিউল ২১-কে সমর্থনকারী ডিপেন্ডেন্সি গ্রাফের জন্য নির্দিষ্ট কিছু প্যাকেজকে বিশেষ ভার্সনে লক করার প্রয়োজন হয়। কিছু প্যাকেজকে অবশ্যই উল্লেখ করতে হবে, এমনকি যদি সেগুলো পাইথন ৩-এর app.yaml ফাইলে নির্দিষ্ট করা না থাকে।

পূর্বে:

flask

একটি কার্যকর মডিউল ২১ অ্যাপ তৈরির জন্য, মডিউল ২০-এর requirements.txt ফাইলটিকে নিম্নলিখিতভাবে আপডেট করুন:

পরে:

grpcio==1.0.0
protobuf<3.18.0
six>=1.13.0
flask
google-gax<0.13.0
google-api-core==1.31.1
google-api-python-client<=1.11.0
google-auth<2.0dev
google-cloud-datastore==1.15.3
google-cloud-firestore==1.9.0
google-cloud-ndb
google-cloud-pubsub==1.7.0
firebase-admin

ডিপেন্ডেন্সি পরিবর্তনের সাথে সাথে রিপোজিটরিতে প্যাকেজ এবং ভার্সন নম্বর আপডেট করা হবে, কিন্তু এই লেখাটির সময় একটি কার্যকরী অ্যাপের জন্য এই app.yaml যথেষ্ট।

অন্যান্য কনফিগারেশন আপডেট

আপনি যদি এই কোডল্যাবের আগের অংশে lib ফোল্ডারটি ডিলিট না করে থাকেন, তবে এখন তা করুন। নতুনভাবে আপডেট করা requirements.txt ফাইলটি দিয়ে, এই রিকোয়ারমেন্টগুলো lib এ ইনস্টল করার জন্য পরিচিত এই কমান্ডটি দিন:

pip install -t lib -r requirements.txt  # or pip2

আপনার ডেভেলপমেন্ট সিস্টেমে যদি পাইথন ২ এবং ৩ উভয়ই ইনস্টল করা থাকে, তাহলে আপনাকে pip এর পরিবর্তে pip2 ব্যবহার করতে হতে পারে।

অ্যাপ্লিকেশন কোড পরিবর্তন করুন

সৌভাগ্যবশত, প্রয়োজনীয় পরিবর্তনগুলোর বেশিরভাগই কনফিগারেশন ফাইলগুলোতে রয়েছে। অ্যাপ্লিকেশন কোডে একমাত্র যে পরিবর্তনটি প্রয়োজন তা হলো, এপিআই অ্যাক্সেস করার জন্য রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরির পরিবর্তে নিম্ন-স্তরের গুগল এপিআই ক্লায়েন্ট লাইব্রেরি ব্যবহার করার জন্য একটি ছোট আপডেট। templates/index.html ওয়েব টেমপ্লেটে কোনো আপডেটের প্রয়োজন নেই।

আমদানি এবং প্রারম্ভিকীকরণ আপডেট করুন

নিচে দেখানো অনুযায়ী, রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরি ( google.cloud.resourcemanager ) কে গুগল এপিআই ক্লায়েন্ট লাইব্রেরি ( googleapiclient.discovery ) দিয়ে প্রতিস্থাপন করুন:

পূর্বে:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb, resourcemanager
from firebase_admin import auth, initialize_app

পরে:

from flask import Flask, render_template, request
from google.auth import default
from google.cloud import ndb
from googleapiclient import discovery
from firebase_admin import auth, initialize_app

অ্যাপ ইঞ্জিন অ্যাডমিন ব্যবহারকারীদের জন্য সহায়তা

নিম্ন-স্তরের ক্লায়েন্ট লাইব্রেরি ব্যবহারের জন্য _get_gae_admins() ফাংশনে কিছু পরিবর্তন প্রয়োজন। প্রথমে কী কী পরিবর্তন হচ্ছে তা আলোচনা করা যাক, তারপর আপডেট করার জন্য সম্পূর্ণ কোডটি আপনাদের দেওয়া হবে।

পাইথন ২ কোডটির জন্য google.auth.default() থেকে প্রাপ্ত ক্রেডেনশিয়াল এবং প্রজেক্ট আইডি উভয়ই ব্যবহার করা প্রয়োজন। পাইথন ৩-এ ক্রেডেনশিয়াল ব্যবহৃত হয় না, তাই এটিকে একটি জেনেরিক আন্ডারস্কোর ( _ ) ডামি ভেরিয়েবলে অ্যাসাইন করা হয়েছিল। যেহেতু পাইথন ২ সংস্করণের জন্য এটি প্রয়োজন, তাই আন্ডারস্কোরটিকে CREDS এ পরিবর্তন করুন। এছাড়াও, একটি রিসোর্স ম্যানেজার এপিআই ক্লায়েন্ট তৈরি করার পরিবর্তে, আপনি একটি এপিআই সার্ভিস এন্ডপয়েন্ট তৈরি করবেন, যা ধারণাগতভাবে একটি এপিআই ক্লায়েন্টের মতোই, তাই আমরা একই ভেরিয়েবলের নাম ( rm_client ) রাখছি। একটি পার্থক্য হলো, একটি সার্ভিস এন্ডপয়েন্ট ইনস্ট্যানশিয়েট করার জন্য ক্রেডেনশিয়াল ( CREDS ) প্রয়োজন হয়।

এই পরিবর্তনগুলো নিচের কোডে প্রতিফলিত হয়েছে:

পূর্বে:

_, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloudplatformprojects.readonly'])
rm_client = resourcemanager.ProjectsClient()

পরে:

CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
        ['https://www.googleapis.com/auth/cloud-platform'])
rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)

আরেকটি পার্থক্য হলো, রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরি allow-policy অবজেক্ট রিটার্ন করে যা ডটেড-অ্যাট্রিবিউট নোটেশন ব্যবহার করে, যেখানে নিম্ন-স্তরের ক্লায়েন্ট লাইব্রেরি পাইথন ডিকশনারি রিটার্ন করে যেখানে স্কয়ার ব্র্যাকেট ( [ ] ) ব্যবহৃত হয়। উদাহরণস্বরূপ, রিসোর্স ম্যানেজার ক্লায়েন্ট লাইব্রেরির জন্য binding.role এবং নিম্ন-স্তরের লাইব্রেরির জন্য binding['role'] ব্যবহৃত হয়। এছাড়াও, প্রথমটি "আন্ডারস্কোর দ্বারা পৃথক করা" নাম ব্যবহার করে, যেখানে নিম্ন-স্তরের লাইব্রেরি "ক্যামেলকেসড" নাম পছন্দ করে এবং এপিআই প্যারামিটার পাস করার পদ্ধতিও কিছুটা ভিন্ন।

ব্যবহারের এই পার্থক্যগুলো নিচে দেখানো হলো:

পূর্বে:

allow_policy = rm_client.get_iam_policy(resource='projects/%s' % PROJ_ID)
for b in allow_policy.bindings:     # bindings in IAM allow-policy
    if b.role in _TARGETS:          # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b.members)

পরে:

allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
for b in allow_policy['bindings']:  # bindings in IAM allow-policy
    if b['role'] in _TARGETS:       # only look at GAE admin roles
        admins.update(user.split(':', 1).pop() for user in b['members'])

এই সমস্ত পরিবর্তন একত্রিত করে, Python 3-এর _get_gae_admins() ফাংশনটিকে এর সমতুল্য Python 2 সংস্করণ দিয়ে প্রতিস্থাপন করুন:

def _get_gae_admins():
    'return set of App Engine admins'
    # setup constants for calling Cloud Resource Manager API
    CREDS, PROJ_ID = default(  # Application Default Credentials and project ID
            ['https://www.googleapis.com/auth/cloud-platform'])
    rm_client = discovery.build('cloudresourcemanager', 'v1', credentials=CREDS)
    _TARGETS = frozenset((     # App Engine admin roles
            'roles/viewer',
            'roles/editor',
            'roles/owner',
            'roles/appengine.appAdmin',
    ))

    # collate users who are members of at least one GAE admin role (_TARGETS)
    admins = set()                      # set of all App Engine admins
    allow_policy = rm_client.projects().getIamPolicy(resource=PROJ_ID).execute()
    for b in allow_policy['bindings']:  # bindings in IAM allow-policy
        if b['role'] in _TARGETS:       # only look at GAE admin roles
            admins.update(user.split(':', 1).pop() for user in b['members'])
    return admins

The is_admin() function doesn't require any updates because it relies on _get_gae_admins() which has already been updated.

This concludes the changes required to backport the Python 3 Module 21 app to Python 2. Congratulations for arriving at your updated Module 21 sample app! You'll find all the code in the Module 21a repo folder .

7. Summary/Cleanup

The last steps in the codelab are to ensure principals (users or service accounts) running this app have the proper permissions to do so, then deploy your app to confirm it works as intended and the changes are reflected in the output.

Ability to read IAM allow-policy

Earlier, we introduced you to the four roles required to be recognized as an App Engine admin user, but there is now a fifth to become familiar with:

  • roles/viewer
  • roles/editor
  • roles/owner
  • roles/appengine.appAdmin
  • roles/resourcemanager.projectIamAdmin (for principals accessing the IAM allow-policy)

The roles/resourcemanager.projectIamAdmin role enables principals to determine whether an end-user is a member of any of the App Engine admin roles. Without membership in roles/resourcemanager.projectIamAdmin , calls to the Cloud Resource Manager API to get the allow-policy will fail.

You do not need to take any explicit action here as your app will run under App Engine's default service account which is automatically granted membership in this role. Even if you use the default service account during the development phase, we strongly recommend creating and using a user-managed service account with the minimal permissions required for your app to function properly. To grant membership to such a service account, run the following command:

$ gcloud projects add-iam-policy-binding PROJ_ID --member="serviceAccount:USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com" --role=roles/resourcemanager.projectIamAdmin

PROJ_ID is the Cloud project ID and USR_MGD_SVC_ACCT@PROJ_ID.iam.gserviceaccount.com is the user-managed service account you create for your app. This command outputs the updated IAM policy for your project where you can confirm the service account has membership in roles/resourcemanager.projectIamAdmin . For more information, see the reference documentation . To repeat, you don't need to issue that command in this codelab, but save this as a reference for modernizing your own apps.

Deploy and verify application

Upload your app to the cloud with the standard gcloud app deploy command. Once deployed, you should see functionality almost identical to the Module 20 app except that you've successfully replaced the App Engine Users service with the Cloud Identity Platform (and Firebase Auth) for user management:

3a83ae745121d70.png

One difference you'll notice compared to Module 20 is that clicking on the Login results in a popup instead of a redirect, captured in some of the screenshots below. Like Module 20 however, the behavior differs slightly depending on how many Google accounts have been registered with the browser.

If there are no users registered with the browser or a single user who hasn't signed in yet, a generic Google Sign-in popup comes up:

8437f5f3d489a942.png

If a single user is registered with your browser but signs-in elsewhere, no dialog appears (or it pops up and closes immediately), and the app goes into a signed-in state (displays the user email and Logout button).

Some developers may want to provide an account-picker, even for a single user:

b75624cb68d94557.png

To implement this, uncomment the provider.setCustomParameters({prompt: 'select_account'}); line in the web template as described earlier.

If there are multiple users, the account-picker dialog pops up (see below). If not signed-in yet, the user will be prompted. If already signed-in, the popup disappears, and the app goes into a signed-in state.

c454455b6020d5e4.png

The signed-in state of Module 21 looks identical to Module 20's user interface:

49ebe4dcc1eff11f.png

The same is true for when an admin user has signed-in:

44302f35b39856eb.png

Unlike Module 21, Module 20 always accesses the logic for the web template content from the app (server-side code). A flaw of the Module 20 is that one visit is registered when the end-user hits the app the first time, and another one is registered when a user signs-in.

For Module 21, the login logic takes place in just the web template (client-side code). There is no required server-side trip to determine what content to display. The only call made to the server is the check for admin users after an end-user signs-in. This means that logins and logouts don't register additional visits, so the most recent visits list stays constant for user management actions. Notice the screenshots above display the same set of four visits across multiple user logins.

The Module 20 screenshots demonstrate the "double-visit bug" at the beginning of this codelab. Separate visits logs are displayed for each sign-in or sign-out action. Check the timestamps of the most recent visit for each screenshot displaying the chronological ordering.

পরিষ্কার করা

সাধারণ

If you are done for now, we recommend you disable your App Engine app to avoid incurring billing. However if you wish to test or experiment some more, the App Engine platform has a free quota , and so as long as you don't exceed that usage tier, you shouldn't be charged. That's for compute, but there may also be charges for relevant App Engine services, so check its pricing page for more information. If this migration involves other Cloud services, those are billed separately. In either case, if applicable, see the "Specific to this codelab" section below.

For full disclosure, deploying to a Google Cloud serverless compute platform like App Engine incurs minor build and storage costs . Cloud Build has its own free quota as does Cloud Storage . Storage of that image uses up some of that quota. However, you might live in a region that does not have such a free tier, so be aware of your storage usage to minimize potential costs. Specific Cloud Storage "folders" you should review include:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • The storage links above depend on your PROJECT_ID and LOC ation, for example, " us " if your app is hosted in the USA.

On the other hand, if you're not going to continue with this application or other related migration codelabs and want to delete everything completely, shut down your project .

Specific to this codelab

The services listed below are unique to this codelab. Refer to each product's documentation for more information:

পরবর্তী পদক্ষেপ

Beyond this tutorial, other migration modules that focus on moving away from the legacy bundled services to consider include:

  • Module 2 : migrate from App Engine ndb to Cloud NDB
  • Modules 7-9 : migrate from App Engine Task Queue (push tasks) to Cloud Tasks
  • Modules 12-13 : migrate from App Engine Memcache to Cloud Memorystore
  • Modules 15-16 : migrate from App Engine Blobstore to Cloud Storage
  • Modules 18-19 : migrate from App Engine Task Queue (pull tasks) to Cloud Pub/Sub

App Engine is no longer the only serverless platform in Google Cloud. If you have a small App Engine app or one that has limited functionality and wish to turn it into a standalone microservice, or you want to break-up a monolithic app into multiple reusable components, these are good reasons to consider moving to Cloud Functions . If containerization has become part of your application development workflow, particularly if it consists of a CI/CD (continuous integration/continuous delivery or deployment) pipeline, consider migrating to Cloud Run . These scenarios are covered by the following modules:

  • Migrate from App Engine to Cloud Functions: see Module 11
  • Migrate from App Engine to Cloud Run: see Module 4 to containerize your app with Docker, or Module 5 to do it without containers, Docker knowledge, or Dockerfile s

Switching to another serverless platform is optional, and we recommend considering the best options for your apps and use cases before making any changes.

Regardless of which migration module you consider next, all Serverless Migration Station content (codelabs, videos, source code [when available]) can be accessed at its open source repo . The repo's README also provides guidance on which migrations to consider and any relevant "order" of Migration Modules.

8. Additional resources

Listed below are additional resources for developers exploring this or related migration modules further. Below, you can provide feedback on this content, find links to the code, and various pieces of documentation you may find useful.

Codelabs issues/feedback

If you find any issues with this codelab, please search for your issue first before filing. Links to search and create new issues:

Migration resources

Links to the repo folders for Module 20 (START) and Module 21 (FINISH) can be found in the table below.

Codelab

Python 2

Python 3

Module 20

কোড

(n/a)

Module 21 (this codelab)

কোড

কোড

Online references

Below are resources relevant for this tutorial:

Cloud Identity Platform and Cloud Marketplace

Cloud Resource Manager, Cloud IAM, Firebase Admin SDK

App Engine Users, App Engine NDB, Cloud NDB, Cloud Datastore

Other Migration Module references

App Engine migration

App Engine platform

Cloud SDK

Other Cloud information

ভিডিও

License

This work is licensed under a Creative Commons Attribution 2.0 Generic License.