Apple এবং C++ ব্যবহার করে প্রমাণীকরণ করুন

আপনি ফায়ারবেস এসডিকে ব্যবহার করে এন্ড-টু-এন্ড OAuth 2.0 সাইন-ইন ফ্লো সম্পন্ন করার মাধ্যমে আপনার ব্যবহারকারীদের তাদের অ্যাপল আইডি দিয়ে ফায়ারবেসে প্রমাণীকরণের সুযোগ দিতে পারেন।

শুরু করার আগে

Apple ব্যবহার করে ব্যবহারকারীদের সাইন ইন করাতে, প্রথমে Apple-এর ডেভেলপার সাইটে ‘Sign In with Apple’ কনফিগার করুন, তারপর আপনার Firebase প্রোজেক্টের জন্য Apple-কে সাইন-ইন প্রদানকারী হিসেবে সক্রিয় করুন।

অ্যাপল ডেভেলপার প্রোগ্রামে যোগ দিন

‘সাইন ইন উইথ অ্যাপল’ শুধুমাত্র অ্যাপল ডেভেলপার প্রোগ্রামের সদস্যরাই কনফিগার করতে পারেন।

অ্যাপল দিয়ে সাইন ইন কনফিগার করুন

আপনার Firebase প্রজেক্টে Apple Sign In অবশ্যই সক্রিয় এবং সঠিকভাবে কনফিগার করা থাকতে হবে। Android এবং Apple প্ল্যাটফর্ম ভেদে এই কনফিগারেশন ভিন্ন হয়। কাজ শুরু করার আগে অনুগ্রহ করে Apple প্ল্যাটফর্ম এবং/অথবা Android গাইডের "Configure Sign In With Apple" অংশটি অনুসরণ করুন।

সাইন-ইন প্রদানকারী হিসেবে অ্যাপলকে সক্রিয় করুন।

  1. Firebase কনসোলে, Security > Authentication- এ যান।
  2. সাইন-ইন পদ্ধতি ট্যাবে, অ্যাপল সাইন-ইন প্রদানকারীকে সক্রিয় করুন।
  3. অ্যাপল সাইন-ইন প্রদানকারীর সেটিংস কনফিগার করুন:
    • অ্যাপল : আপনি যদি আপনার অ্যাপটি শুধুমাত্র অ্যাপল প্ল্যাটফর্মে স্থাপন করেন, তাহলে আপনি সার্ভিস আইডি, অ্যাপল টিম আইডি, প্রাইভেট কী এবং কী আইডি ফিল্ডগুলো খালি রাখতে পারেন।
    • অ্যান্ড্রয়েড : অ্যান্ড্রয়েড ডিভাইস সমর্থন করার জন্য নিম্নলিখিতগুলি সম্পূর্ণ করুন:
      1. আপনার অ্যান্ড্রয়েড প্রজেক্টে ফায়ারবেস যুক্ত করুন
      2. আপনার অ্যাপের SHA-1 ফিঙ্গারপ্রিন্টটি আগে থেকে নির্দিষ্ট করা না থাকলে, তা করে নিন।
        1. Firebase কনসোলে, এখানে যান > সাধারণ ট্যাব
        2. নিচে স্ক্রল করে 'Your apps' কার্ডে যান, আপনার অ্যান্ড্রয়েড অ্যাপটি নির্বাচন করুন এবং 'SHA certificate fingerprints' ফিল্ডে আপনার SHA-1 ফিঙ্গারপ্রিন্ট যোগ করুন।

        আপনার অ্যাপের SHA ফিঙ্গারপ্রিন্ট কীভাবে পাবেন, সে সম্পর্কে বিস্তারিত জানতে ‘আপনার ক্লায়েন্ট প্রমাণীকরণ’ দেখুন।

      3. অ্যাপল সাইন-ইন প্রদানকারীর সেটিংস কনফিগার করুন:
        1. Firebase কনসোলে, Security > Authentication- এ যান।
        2. সাইন-ইন পদ্ধতি ট্যাবে, অ্যাপল সাইন-ইন প্রদানকারীতে ক্লিক করুন।
        3. পূর্ববর্তী বিভাগে আপনার তৈরি করা সার্ভিস আইডিটি উল্লেখ করুন। এছাড়াও, OAuth কোড ফ্লো কনফিগারেশন বিভাগে, আপনার অ্যাপল টিম আইডি এবং পূর্ববর্তী বিভাগে আপনার তৈরি করা প্রাইভেট কী ও কী আইডি উল্লেখ করুন।

অ্যাপলের পরিচয় গোপন রাখার শর্তাবলী মেনে চলুন

সাইন ইন করার সময়, ‘সাইন ইন উইথ অ্যাপল’ ব্যবহারকারীদের তাদের ইমেল ঠিকানা সহ ডেটা গোপন করার বিকল্প দেয়। যে ব্যবহারকারীরা এই বিকল্পটি বেছে নেন, তাদের ইমেল ঠিকানার ডোমেইন হয় privaterelay.appleid.com । আপনি যখন আপনার অ্যাপে ‘সাইন ইন উইথ অ্যাপল’ ব্যবহার করবেন, তখন এই গোপনকৃত অ্যাপল আইডিগুলো সম্পর্কিত অ্যাপলের প্রযোজ্য ডেভেলপার নীতি বা শর্তাবলী আপনাকে অবশ্যই মেনে চলতে হবে।

এর মধ্যে একটি বেনামী Apple ID-র সাথে সরাসরি শনাক্তকারী ব্যক্তিগত তথ্য যুক্ত করার আগে ব্যবহারকারীর প্রয়োজনীয় সম্মতি গ্রহণ করা অন্তর্ভুক্ত। Firebase Authentication ব্যবহার করার সময়, এর মধ্যে নিম্নলিখিত পদক্ষেপগুলি অন্তর্ভুক্ত থাকতে পারে:

  • একটি ইমেল ঠিকানাকে একটি বেনামী অ্যাপল আইডির সাথে লিঙ্ক করুন অথবা এর বিপরীতটিও করুন।
  • একটি ফোন নম্বরকে একটি বেনামী অ্যাপল আইডির সাথে লিঙ্ক করুন অথবা এর বিপরীতটি করুন
  • একটি পরিচয়বিহীন অ্যাপল আইডির সাথে একটি পরিচয়বিহীন সোশ্যাল ক্রেডেনশিয়াল (ফেসবুক, গুগল, ইত্যাদি) লিঙ্ক করুন অথবা এর বিপরীতটি করুন।

উপরের তালিকাটি সম্পূর্ণ নয়। আপনার অ্যাপটি অ্যাপলের শর্তাবলী পূরণ করছে কিনা, তা নিশ্চিত করতে আপনার ডেভেলপার অ্যাকাউন্টের মেম্বারশিপ বিভাগে থাকা অ্যাপল ডেভেলপার প্রোগ্রাম লাইসেন্স চুক্তিটি দেখুন।

firebase::auth::Auth ক্লাস অ্যাক্সেস করুন

Auth ক্লাসটি সকল API কলের প্রবেশদ্বার।
  1. Auth এবং App হেডার ফাইলগুলো যোগ করুন:
    #include "firebase/app.h"
    #include "firebase/auth.h"
  2. আপনার ইনিশিয়ালাইজেশন কোডে একটি firebase::App ক্লাস তৈরি করুন।
    #if defined(__ANDROID__)
      firebase::App* app =
          firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity);
    #else
      firebase::App* app = firebase::App::Create(firebase::AppOptions());
    #endif  // defined(__ANDROID__)
  3. আপনার firebase::App জন্য firebase::auth::Auth ক্লাসটি অ্যাকোয়ার করুন। App এবং Auth মধ্যে একটি এক-এক ম্যাপিং রয়েছে।
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);

Firebase SDK দিয়ে সাইন-ইন প্রক্রিয়াটি পরিচালনা করুন।

অ্যাপল এবং অ্যান্ড্রয়েড প্ল্যাটফর্মে 'অ্যাপল দিয়ে সাইন-ইন' করার প্রক্রিয়া ভিন্ন ভিন্ন হয়ে থাকে।

অ্যাপল প্ল্যাটফর্মে

আপনার C++ কোড থেকে কল করা Apple Sign In Objective-C SDK-এর মাধ্যমে Firebase-এ আপনার ব্যবহারকারীদের প্রমাণীকরণ করুন।

  1. প্রতিটি সাইন-ইন অনুরোধের জন্য, একটি র‍্যান্ডম স্ট্রিং—একটি 'নন্স'—তৈরি করুন, যা ব্যবহার করে আপনি নিশ্চিত করবেন যে আপনার প্রাপ্ত আইডি টোকেনটি বিশেষভাবে আপনার অ্যাপের প্রমাণীকরণ অনুরোধের জবাবেই প্রদান করা হয়েছে। রিপ্লে অ্যাটাক প্রতিরোধ করার জন্য এই পদক্ষেপটি গুরুত্বপূর্ণ।

      - (NSString *)randomNonce:(NSInteger)length {
        NSAssert(length > 0, @"Expected nonce to have positive length");
        NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
        NSMutableString *result = [NSMutableString string];
        NSInteger remainingLength = length;
    
        while (remainingLength > 0) {
          NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16];
          for (NSInteger i = 0; i < 16; i++) {
            uint8_t random = 0;
            int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random);
            NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode);
    
            [randoms addObject:@(random)];
          }
    
          for (NSNumber *random in randoms) {
            if (remainingLength == 0) {
              break;
            }
    
            if (random.unsignedIntValue < characterSet.length) {
              unichar character = [characterSet characterAtIndex:random.unsignedIntValue];
              [result appendFormat:@"%C", character];
              remainingLength--;
            }
          }
        }
      }
    
    

    আপনি আপনার সাইন-ইন অনুরোধের সাথে ননস-এর SHA256 হ্যাশ পাঠাবেন, যা অ্যাপল অপরিবর্তিতভাবে রেসপন্সে পাঠাবে। ফায়ারবেস মূল ননস-কে হ্যাশ করে এবং অ্যাপলের পাঠানো মানের সাথে তুলনা করে রেসপন্সটি যাচাই করে।

  2. আপনার অনুরোধে ননসের SHA256 হ্যাশ এবং অ্যাপলের প্রতিক্রিয়া পরিচালনা করবে এমন ডেলিগেট ক্লাস অন্তর্ভুক্ত করে অ্যাপলের সাইন-ইন প্রক্রিয়াটি শুরু করুন (পরবর্তী ধাপ দেখুন):

      - (void)startSignInWithAppleFlow {
        NSString *nonce = [self randomNonce:32];
        self.currentNonce = nonce;
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest];
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        request.nonce = [self stringBySha256HashingString:nonce];
    
        ASAuthorizationController *authorizationController =
            [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        authorizationController.delegate = self;
        authorizationController.presentationContextProvider = self;
        [authorizationController performRequests];
      }
    
      - (NSString *)stringBySha256HashingString:(NSString *)input {
        const char *string = [input UTF8String];
        unsigned char result[CC_SHA256_DIGEST_LENGTH];
        CC_SHA256(string, (CC_LONG)strlen(string), result);
    
        NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
        for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
          [hashed appendFormat:@"%02x", result[i]];
        }
        return hashed;
      }
    
  3. আপনার `ASAuthorizationControllerDelegate`-এর বাস্তবায়নে Apple-এর প্রতিক্রিয়াটি পরিচালনা করুন। যদি সাইন-ইন সফল হয়, তাহলে Firebase-এর সাথে প্রমাণীকরণের জন্য Apple-এর প্রতিক্রিয়া থেকে প্রাপ্ত ID টোকেনটি আনহ্যাশড ননস (nonce)-এর সাথে ব্যবহার করুন:

      - (void)authorizationController:(ASAuthorizationController *)controller
         didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
        if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
          ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
          NSString *rawNonce = self.currentNonce;
          NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent.");
    
          if (appleIDCredential.identityToken == nil) {
            NSLog(@"Unable to fetch identity token.");
            return;
          }
    
          NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken
                                                    encoding:NSUTF8StringEncoding];
          if (idToken == nil) {
            NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken);
          }
        }
    
  4. প্রাপ্ত টোকেন স্ট্রিং এবং মূল ননস ব্যবহার করে একটি ফায়ারবেস ক্রেডেনশিয়াল তৈরি করুন এবং ফায়ারবেসে সাইন ইন করুন।

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  5. একই পদ্ধতি Reauthenticate ক্ষেত্রেও ব্যবহার করা যেতে পারে, যা সাম্প্রতিক লগইন প্রয়োজন এমন সংবেদনশীল কার্যক্রমের জন্য নতুন ক্রেডেনশিয়াল পুনরুদ্ধার করতে কাজে লাগে।

    firebase::Future<firebase::auth::AuthResult> result =
        user->Reauthenticate(credential);
    
  6. অ্যাপল সাইন ইন-এর সাথে একটি অ্যাকাউন্ট লিঙ্ক করার জন্য একই প্যাটার্ন ব্যবহার করা যেতে পারে। তবে, আপনি যে অ্যাপল অ্যাকাউন্টটি লিঙ্ক করার চেষ্টা করছেন, সেটির সাথে যদি আগে থেকেই একটি ফায়ারবেস অ্যাকাউন্ট লিঙ্ক করা থাকে, তাহলে আপনি একটি ত্রুটির সম্মুখীন হতে পারেন। যখন এটি ঘটে, তখন `future` ফাংশনটি kAuthErrorCredentialAlreadyInUse স্ট্যাটাস রিটার্ন করবে এবং ` AuthResult একটি বৈধ credential থাকতে পারে। এই ক্রেডেনশিয়ালটি ব্যবহার করে, অন্য কোনো অ্যাপল সাইন ইন টোকেন এবং ননস তৈরি করার প্রয়োজন ছাড়াই SignInAndRetrieveDataWithCredential এর মাধ্যমে অ্যাপল-লিঙ্ক করা অ্যাকাউন্টে সাইন ইন করা যাবে।

    firebase::Future<firebase::auth::AuthResult> link_result =
        auth->current_user().LinkWithCredential(credential);
    
    // To keep example simple, wait on the current thread until call completes.
    while (link_result.status() == firebase::kFutureStatusPending) {
      Wait(100);
    }
    
    // Determine the result of the link attempt
    if (link_result.error() == firebase::auth::kAuthErrorNone) {
      // user linked correctly.
    } else if (link_result.error() ==
                   firebase::auth::kAuthErrorCredentialAlreadyInUse &&
               link_result.result()
                   ->additional_user_info.updated_credential.is_valid()) {
      // Sign In with the new credential
      firebase::Future<firebase::auth::AuthResult> result =
          auth->SignInAndRetrieveDataWithCredential(
              link_result.result()->additional_user_info.updated_credential);
    } else {
      // Another link error occurred.
    }

অ্যান্ড্রয়েডে

অ্যান্ড্রয়েডে, সম্পূর্ণ সাইন-ইন প্রক্রিয়াটি সম্পন্ন করার জন্য Firebase SDK ব্যবহার করে আপনার অ্যাপে ওয়েব-ভিত্তিক জেনেরিক OAuth লগইন ইন্টিগ্রেট করুন এবং এর মাধ্যমে Firebase-এর সাহায্যে ব্যবহারকারীদের প্রমাণীকরণ করুন।

Firebase SDK ব্যবহার করে সাইন-ইন প্রক্রিয়াটি পরিচালনা করতে, এই ধাপগুলো অনুসরণ করুন:

  1. Apple-এর জন্য উপযুক্ত প্রোভাইডার আইডি দিয়ে কনফিগার করা একটি FederatedOAuthProviderData ইনস্ট্যান্স তৈরি করুন।

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. ঐচ্ছিক: ডিফল্ট স্কোপের বাইরে অতিরিক্ত যে OAuth 2.0 স্কোপগুলো আপনি অথেনটিকেশন প্রোভাইডারের কাছ থেকে অনুরোধ করতে চান, তা নির্দিষ্ট করুন।

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. ঐচ্ছিক: আপনি যদি অ্যাপলের সাইন-ইন স্ক্রিনটি ইংরেজি ছাড়া অন্য কোনো ভাষায় প্রদর্শন করতে চান, তাহলে locale প্যারামিটারটি সেট করুন। সমর্থিত লোকেলগুলো জানতে ‘ সাইন ইন উইথ অ্যাপল’ ডকুমেন্টেশন দেখুন।

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. আপনার প্রোভাইডার ডেটা কনফিগার করা হয়ে গেলে, সেটি ব্যবহার করে একটি FederatedOAuthProvider তৈরি করুন।

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Auth প্রোভাইডার অবজেক্ট ব্যবহার করে Firebase-এর সাথে প্রমাণীকরণ করুন। উল্লেখ্য যে, অন্যান্য FirebaseAuth অপারেশনের মতো নয়, এটি একটি ওয়েব ভিউ পপ-আপ করে আপনার UI-এর নিয়ন্ত্রণ নেবে, যেখানে ব্যবহারকারী তার ক্রেডেনশিয়াল প্রবেশ করাতে পারবেন।

    সাইন ইন প্রক্রিয়া শুরু করতে, signInWithProvider কল করুন:

    firebase::Future<firebase::auth::AuthResult> result =
      auth->SignInWithProvider(provider_data);
    

    এরপর আপনার অ্যাপ্লিকেশনটি অপেক্ষা করতে পারে অথবা Future-এ একটি কলব্যাক রেজিস্টার করতে পারে

  6. ReauthenticateWithProvider সাথেও একই প্যাটার্ন ব্যবহার করা যেতে পারে, যা সাম্প্রতিক লগইন প্রয়োজন এমন সংবেদনশীল অপারেশনের জন্য নতুন ক্রেডেনশিয়াল পুনরুদ্ধার করতে কাজে লাগে।

    firebase::Future<firebase::auth::AuthResult> result =
      user.ReauthenticateWithProvider(provider_data);
    

    এরপর আপনার অ্যাপ্লিকেশনটি অপেক্ষা করতে পারে অথবা Future-এ একটি কলব্যাক রেজিস্টার করতে পারে

  7. এবং, আপনি বিদ্যমান অ্যাকাউন্টগুলোর সাথে বিভিন্ন আইডেন্টিটি প্রোভাইডার লিঙ্ক করতে LinkWithCredential() ব্যবহার করতে পারেন।

    মনে রাখবেন যে, ব্যবহারকারীদের অ্যাপল অ্যাকাউন্ট অন্য ডেটার সাথে লিঙ্ক করার আগে অ্যাপল আপনাকে তাদের কাছ থেকে সুস্পষ্ট সম্মতি নিতে বলে।

    উদাহরণস্বরূপ, বর্তমান Firebase অ্যাকাউন্টের সাথে একটি Facebook অ্যাকাউন্ট লিঙ্ক করতে, Facebook-এ ব্যবহারকারীকে সাইন ইন করার সময় আপনি যে অ্যাক্সেস টোকেনটি পেয়েছেন তা ব্যবহার করুন:

    // Initialize a Facebook credential with a Facebook access token.
    AuthCredential credential =
        firebase::auth::FacebookAuthProvider.getCredential(token);
    
    // Assuming the current user is an Apple user linking a Facebook provider.
    firebase::Future<firebase::auth::AuthResult> result =
        auth.current_user().LinkWithCredential(credential);
    

অ্যাপল নোটস দিয়ে সাইন ইন করুন

Firebase Auth দ্বারা সমর্থিত অন্যান্য প্রদানকারীদের থেকে ভিন্ন, Apple ছবির কোনো URL প্রদান করে না।

এছাড়াও, যখন ব্যবহারকারী অ্যাপের সাথে তাদের ইমেল শেয়ার না করার সিদ্ধান্ত নেন, তখন অ্যাপল সেই ব্যবহারকারীর জন্য একটি অনন্য ইমেল ঠিকানা ( xyz@privaterelay.appleid.com ফর্ম্যাটে) তৈরি করে, যা আপনার অ্যাপের সাথে শেয়ার করা হয়। আপনি যদি প্রাইভেট ইমেল রিলে পরিষেবাটি কনফিগার করে থাকেন, তাহলে অ্যাপল সেই বেনামী ঠিকানায় পাঠানো ইমেলগুলি ব্যবহারকারীর আসল ইমেল ঠিকানায় ফরোয়ার্ড করে দেয়।

কোনো ব্যবহারকারী প্রথমবার সাইন ইন করার সময়ই অ্যাপল শুধুমাত্র ডিসপ্লে নেমের মতো ব্যবহারকারীর তথ্য অ্যাপগুলোর সাথে শেয়ার করে। সাধারণত, কোনো ব্যবহারকারী প্রথমবার অ্যাপল দিয়ে সাইন ইন করলে ফায়ারবেস ডিসপ্লে নেমটি সংরক্ষণ করে, যা আপনি current_user().display_name() এর মাধ্যমে পেতে পারেন। তবে, আপনি যদি আগে ফায়ারবেস ব্যবহার না করে অ্যাপলের মাধ্যমে কোনো ব্যবহারকারীকে অ্যাপটিতে সাইন ইন করিয়ে থাকেন, তাহলে অ্যাপল ফায়ারবেসকে ব্যবহারকারীর ডিসপ্লে নেমটি সরবরাহ করবে না।

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

কোনো ব্যবহারকারী প্রথমবার সাইন ইন করার পর, একটি নতুন ব্যবহারকারী অ্যাকাউন্ট তৈরি হয় এবং সেটি ব্যবহারকারীর সাইন ইন করার ক্রেডেনশিয়াল—অর্থাৎ, ইউজার নেম ও পাসওয়ার্ড, ফোন নম্বর, বা অথোরাইজেশন প্রোভাইডারের তথ্যের—সাথে লিঙ্ক করা হয়। এই নতুন অ্যাকাউন্টটি আপনার ফায়ারবেস প্রজেক্টের অংশ হিসেবে সংরক্ষিত থাকে এবং ব্যবহারকারী কীভাবে সাইন ইন করছেন তা নির্বিশেষে, আপনার প্রজেক্টের প্রতিটি অ্যাপে তাকে শনাক্ত করতে এটি ব্যবহার করা যেতে পারে।

আপনার অ্যাপগুলিতে, আপনি firebase::auth::User অবজেক্ট থেকে ব্যবহারকারীর প্রাথমিক প্রোফাইল তথ্য পেতে পারেন। `ব্যবহারকারী পরিচালনা` দেখুন।

আপনার Firebase Realtime Database and Cloud Storage Security Rules-এ, আপনি auth ভেরিয়েবল থেকে সাইন-ইন করা ব্যবহারকারীর অনন্য ইউজার আইডি পেতে পারেন এবং এটি ব্যবহার করে একজন ব্যবহারকারী কোন ডেটা অ্যাক্সেস করতে পারবে তা নিয়ন্ত্রণ করতে পারেন।