اتصال امن داده با مجوز و تأیید، اتصال داده امن با مجوز و تأیید، اتصال داده امن با مجوز و تأیید

Firebase Data Connect امنیت قوی سمت کلاینت را با موارد زیر فراهم می کند:

  • مجوز موبایل و مشتری وب
  • کنترل های مجوز در سطح پرس و جو و جهش
  • تأیید برنامه با Firebase App Check .

Data Connect این امنیت را با موارد زیر گسترش می دهد:

  • مجوز سمت سرور
  • پروژه Firebase و امنیت کاربر Cloud SQL با IAM.

درخواست‌ها و جهش‌های مشتری را مجاز کنید

Data Connect به طور کامل با Firebase Authentication ادغام شده است، بنابراین می توانید از داده های غنی در مورد کاربرانی که به داده های شما (احراز هویت) دسترسی دارند در طراحی خود استفاده کنید تا به چه داده هایی دسترسی داشته باشید (مجوز).

Data Connect یک دستورالعمل @auth برای پرس و جوها و جهش ها ارائه می دهد که به شما امکان می دهد سطح احراز هویت مورد نیاز برای مجوز عملیات را تنظیم کنید. این راهنما دستورالعمل @auth را با مثال‌هایی معرفی می‌کند .

علاوه بر این، Data Connect از اجرای پرس‌و‌جوهای تعبیه‌شده در جهش‌ها پشتیبانی می‌کند، بنابراین می‌توانید معیارهای مجوز اضافی را که در پایگاه داده‌تان ذخیره کرده‌اید بازیابی کنید و از آن معیارها در دستورالعمل‌های @check برای تصمیم‌گیری در مورد مجاز بودن جهش‌های محصور استفاده کنید. برای این مورد مجوز، دستورالعمل @redact به شما امکان می‌دهد کنترل کنید که آیا نتایج پرس و جو به کلاینت‌ها در پروتکل سیمی بازگردانده می‌شوند و پرس و جوی تعبیه‌شده در SDK‌های تولید شده حذف می‌شوند. مقدمه این دستورالعمل ها را با مثال بیابید.

دستورالعمل @auth را درک کنید

می‌توانید دستورالعمل @auth را برای دنبال کردن یکی از چندین سطح دسترسی از پیش تعیین شده که بسیاری از سناریوهای دسترسی رایج را پوشش می‌دهد، پارامتر کنید. این سطوح از PUBLIC (که امکان درخواست‌ها و جهش‌ها را از همه کلاینت‌ها بدون احراز هویت از هر نوع می‌دهد) تا NO_ACCESS (که درخواست‌ها و جهش‌های خارج از محیط‌های سرور ممتاز را با استفاده از Firebase Admin SDK غیرمجاز می‌کند) متغیر است. هر یک از این سطوح با جریان های احراز هویت ارائه شده توسط Firebase Authentication همبستگی دارد.

سطح تعریف
PUBLIC این عملیات می تواند توسط هر کسی با یا بدون احراز هویت اجرا شود.
PUBLIC این عملیات می تواند توسط هر کسی با یا بدون احراز هویت اجرا شود.
USER_ANON هر کاربر شناسایی شده، از جمله کاربرانی که به طور ناشناس با Firebase Authentication وارد سیستم شده اند، مجاز به انجام پرس و جو یا جهش هستند.
USER هر کاربری که با Firebase Authentication وارد شده باشد، مجاز به انجام پرس و جو یا جهش است به جز کاربران ناشناس ورود به سیستم.
USER_EMAIL_VERIFIED هر کاربری که با Firebase Authentication با آدرس ایمیل تایید شده وارد شده باشد، مجاز به انجام پرس و جو یا جهش است.
NO_ACCESS این عملیات را نمی توان خارج از زمینه مدیریت SDK اجرا کرد.

با استفاده از این سطوح دسترسی از پیش تعیین شده به عنوان نقطه شروع، می‌توانید بررسی‌های مجوز پیچیده و قوی را در دستورالعمل @auth با استفاده where فیلترها و عبارات Common Expression Language (CEL) که در سرور ارزیابی می‌شوند، تعریف کنید.

از دستورالعمل @auth برای اجرای سناریوهای مجوز مشترک استفاده کنید

سطوح دسترسی از پیش تعیین شده نقطه شروع مجوز هستند.

سطح دسترسی USER مفیدترین سطح پایه برای شروع است.

دسترسی کاملاً ایمن در سطح USER به اضافه فیلترها و عباراتی است که ویژگی‌های کاربر، ویژگی‌های منبع، نقش‌ها و بررسی‌های دیگر را بررسی می‌کند. سطوح USER_ANON و USER_EMAIL_VERIFIED تغییراتی در مورد USER هستند.

نحو بیان به شما امکان می‌دهد داده‌ها را با استفاده از یک شیء auth که داده‌های احراز هویت ارسال شده با عملیات را نشان می‌دهد، هم داده‌های استاندارد در نشانه‌های احراز هویت و هم داده‌های سفارشی در نشانه‌ها، ارزیابی کنید. برای لیست فیلدهای موجود در شی auth ، بخش مرجع را ببینید.

البته مواردی وجود دارد که برای شروع، PUBLIC سطح دسترسی صحیح است. باز هم، سطح دسترسی همیشه نقطه شروع است و فیلترها و عبارات اضافی برای امنیت قوی مورد نیاز است.

این راهنما اکنون نمونه هایی از نحوه ساخت بر روی USER و PUBLIC را ارائه می دهد.

یک مثال انگیزشی

بهترین نمونه‌های عملی زیر به طرح زیر برای یک پلتفرم وبلاگ نویسی با محتوای خاصی که پشت یک طرح پرداخت قفل شده است اشاره دارد.

چنین پلتفرمی احتمالاً Users و Posts الگوبرداری می‌کند.

type User @table(key: "uid") {
  uid: String!
  name: String
  birthday: Date
  createdAt: Timestamp! @default(expr: "request.time")
}

type Post @table {
  author: User!
  text: String!
  # "one of 'draft', 'public', or 'pro'"
  visibility: String! @default(value: "draft")
  # "the time at which the post should be considered published. defaults to
  # immediately"
  publishedAt: Timestamp! @default(expr: "request.time")
  createdAt: Timestamp! @default(expr: "request.time")
  updatedAt: Timestamp! @default(expr: "request.time")
}

منابع متعلق به کاربر

Firebase توصیه می‌کند که فیلترها و عباراتی بنویسید که مالکیت کاربر یک منبع را آزمایش می‌کند، در موارد زیر، مالکیت Posts .

در مثال‌های زیر، داده‌های نشانه‌های auth با استفاده از عبارات خوانده و مقایسه می‌شوند. الگوی معمولی استفاده از عباراتی مانند where: {authorUid: {eq_expr: "auth.uid"}} برای مقایسه یک authorUid ذخیره شده با auth.uid (شناسه کاربر) ارسال شده در کد احراز هویت است.

ایجاد کنید

این روش مجوز با اضافه کردن auth.uid از نشانه auth به هر Post جدید به عنوان یک فیلد authorUid شروع می شود تا امکان مقایسه در تست های مجوز بعدی را فراهم کند.

# Create a new post as the current user
mutation CreatePost($text: String!, $visibility: String) @auth(level: USER) {
  post_insert(data: {
    # set the author's uid to the current user uid
    authorUid_expr: "auth.uid"
    text: $text
    visibility: $visibility
  })
}
به روز رسانی

هنگامی که مشتری تلاش می کند یک Post به روز کند، می توانید auth.uid تصویب شده را در برابر authorUid ذخیره شده آزمایش کنید.

# Update one of the current user's posts
mutation UpdatePost($id: UUID!, $text: String, $visibility: String) @auth(level:USER) {
  post_update(
    # only update posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
    data: {
      text: $text
      visibility: $visibility
      # insert the current server time for updatedAt
      updatedAt_expr: "request.time"
    }
  )
}
حذف کنید

از همین تکنیک برای مجوز عملیات حذف استفاده می شود.

# Delete one of the current user's posts
mutation DeletePost($id: UUID!) @auth(level: USER) {
  post_delete(
    # only delete posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
  )
}
# Common display information for a post
fragment DisplayPost on Post {
  id, text, createdAt, updatedAt
  author { uid, name }
}
فهرست کنید
# List all posts belonging to the current user
query ListMyPosts @auth(level: USER) {
  posts(where: {
    userUid: {eq_expr: "auth.uid"}
  }) {
    # See the fragment above
    ...DisplayPost
    # also show visibility since it is user-controlled
    visibility
  }
}
دریافت کنید
# Get a post only if it belongs to the current user
query GetMyPost($id: UUID!) @auth(level: USER) {
  post(key: {id: $id},
    first: {where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}}
      }}, {
      # See the fragment above
      ...DisplayPost
      # also show visibility since it is user-controlled
      visibility
  }
}

فیلتر کردن داده ها

سیستم مجوز Data Connect به شما امکان می‌دهد فیلترهای پیچیده را همراه با سطوح دسترسی از پیش تعیین شده مانند PUBLIC و همچنین با استفاده از داده‌های نشانه‌های احراز هویت بنویسید.

سیستم مجوز همچنین به شما امکان می دهد فقط از عبارات استفاده کنید، بدون سطح دسترسی پایه، همانطور که در برخی از مثال های زیر نشان داده شده است.

فیلتر بر اساس ویژگی های منبع

در اینجا، مجوز بر اساس نشانه‌های اعتبار نیست زیرا سطح امنیت پایه روی PUBLIC تنظیم شده است. اما، ما می توانیم به صراحت رکوردهایی را در پایگاه داده خود به عنوان مناسب برای دسترسی عمومی تنظیم کنیم. فرض کنید رکوردهای Post در پایگاه داده خود داریم با visibility روی "عمومی".

# List all posts marked as 'public' visibility
query ListPublicPosts @auth(level: PUBLIC) {
  posts(where: {
    # Test that visibility is "public"
    visibility: {eq: "public"}
    # Only display articles that are already published
    publishedAt: {lt_expr: "request.time"}
  }) {
    # see the fragment above
    ...DisplayPost
  }
}
بر اساس ادعای کاربر فیلتر کنید

در اینجا، فرض کنید ادعاهای کاربر سفارشی را تنظیم کرده‌اید که توکن‌های تأیید اعتبار را برای شناسایی کاربران در یک طرح «حرفه‌ای» برای برنامه‌تان تنظیم کرده‌اید که با یک فیلد auth.token.plan در نشانه تأیید علامت‌گذاری شده است. عبارات شما می تواند در برابر این زمینه آزمایش شود.

# List all public or pro posts, only permitted if user has "pro" plan claim
query ProListPosts @auth(expr: "auth.token.plan == 'pro'") {
  posts(where: {
    # display both public posts and "pro" posts
    visibility: {in: ['public', 'pro']},
    # only display articles that are already published
    publishedAt: {lt_expr: "request.time"},
  }) {
    # see the fragment above
    ...DisplayPost
    # show visibility so pro users can see which posts are pro\
    visibility
  }
}
فیلتر بر اساس سفارش + محدودیت

یا دوباره، ممکن است visibility در رکوردهای Post تنظیم کرده باشید تا مشخص کنید که محتوای آنها برای کاربران حرفه‌ای در دسترس است، اما برای پیش‌نمایش یا فهرست تیزر داده‌ها، تعداد رکوردهای بازگردانده شده را بیشتر محدود کنید.

# Show 2 oldest Pro post as a preview
query ProTeaser @auth(level: USER) {
  posts(
    where: {
      # show only pro posts
      visibility: {eq: "pro"}
      # that have already been published more than 30 days ago
      publishedAt: {lt_time: {now: true, sub: {days: 30}}}
    },
    # order by publish time
    orderBy: [{publishedAt: DESC}],
    # only return two posts
    limit: 2
  ) {
    # See the fragment above
    ...DisplayPost
  }
}
بر اساس نقش فیلتر کنید

اگر ادعای سفارشی شما نقش admin را تعریف می‌کند، می‌توانید بر این اساس عملیات را آزمایش و مجوز دهید.

# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
  posts { ...DisplayPost }
}

دستورالعمل‌های @check و @redact را درک کنید

دستور @check تأیید می کند که فیلدهای مشخص شده در نتایج پرس و جو وجود دارند. یک عبارت Common Expression Language (CEL) برای آزمایش مقادیر فیلد استفاده می شود. رفتار پیش‌فرض دستورالعمل این است که گره‌های null -valued را بررسی و رد کند.

دستور @redact بخشی از پاسخ مشتری را ویرایش می کند. فیلدهای ویرایش شده هنوز از نظر عوارض جانبی (از جمله تغییرات داده‌ها و @check ) ارزیابی می‌شوند و نتایج هنوز برای مراحل بعدی در عبارات CEL در دسترس هستند.

در Data Connect ، دستورالعمل‌های @check و @redact اغلب در چارچوب بررسی‌های مجوز استفاده می‌شوند. به بحث جستجوی داده های مجوز مراجعه کنید.

دستورالعمل‌های @check و @redact را برای جستجوی داده‌های مجوز اضافه کنید

یک مورد معمول استفاده از مجوز شامل ذخیره نقش‌های مجوز سفارشی در پایگاه داده شما، به عنوان مثال در یک جدول مجوزهای ویژه، و استفاده از آن نقش‌ها برای مجوز دادن به جهش‌ها برای ایجاد، به‌روزرسانی یا حذف داده‌ها است.

با استفاده از جستجوی داده های مجوز، می توانید نقش ها را بر اساس شناسه کاربری جستجو کنید و از عبارات CEL برای تصمیم گیری در مورد مجاز بودن جهش استفاده کنید. به عنوان مثال، ممکن است بخواهید یک جهش UpdateMovieTitle بنویسید که به مشتری مجاز اجازه می دهد عناوین فیلم را به روز کند.

برای بقیه این بحث، فرض کنید پایگاه داده برنامه بررسی فیلم یک نقش مجوز را در جدول MoviePermission ذخیره می کند.

# MoviePermission
# Suppose a user has an authorization role with respect to records in the Movie table
type MoviePermission @table(key: ["doc", "userId"]) {
  movie: Movie! # implies another field: movieId: UUID!
  userId: String! # Can also be a reference to a User table, doesn't matter
  role: String!
}

در اجرای مثال زیر، جهش UpdateMovieTitle شامل یک فیلد query برای بازیابی داده ها از MoviePermission و دستورالعمل های زیر برای اطمینان از ایمن و قوی بودن عملیات است:

  • یک دستورالعمل @transaction برای اطمینان از تکمیل یا عدم موفقیت اتمی تمام درخواست‌ها و بررسی‌های مجوز.
  • دستور @redact برای حذف نتایج جستجو از پاسخ، به این معنی که بررسی مجوز ما در سرور Data Connect انجام می‌شود اما داده‌های حساس در معرض مشتری قرار نمی‌گیرند.
  • یک جفت دستور @check برای ارزیابی منطق مجوز در نتایج پرس و جو، مانند آزمایش اینکه یک شناسه کاربری معین نقش مناسبی برای ایجاد تغییرات دارد.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    # Step 1a: Use @check to test if the user has any role associated with the movie
    # Here the `this` binding refers the lookup result, i.e. a MoviePermission object or null
    # The `this != null` expression could be omitted since rejecting on null is default behavior
    ) @check(expr: "this != null", message: "You do not have access to this movie") {
      # Step 1b: Check if the user has the editor role for the movie
      # Next we execute another @check; now `this` refers to the contents of the `role` field
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

ضد الگوهایی که در مجوز باید از آنها اجتناب کرد

بخش قبل الگوهایی را پوشش می‌دهد که باید هنگام استفاده از دستورالعمل @auth دنبال شوند.

همچنین باید از ضد الگوهای مهمی که باید اجتناب کنید آگاه باشید.

از ارسال شناسه‌های ویژگی‌های کاربر و پارامترهای نشانه تأیید اعتبار در آرگومان‌های پرس و جو و جهش خودداری کنید

Firebase Authentication یک ابزار قدرتمند برای ارائه جریان های احراز هویت و گرفتن ایمن داده های احراز هویت مانند شناسه های کاربر ثبت شده و فیلدهای متعدد ذخیره شده در نشانه های احراز هویت است.

انتقال شناسه‌های کاربر و تأیید داده‌های نشانه در آرگومان‌های پرس و جو و جهش، یک روش توصیه‌شده نیست.

# Antipattern!
# This incorrectly allows any user to view any other user's posts
query AllMyPosts($userId: String!) @auth(level: USER) {
  posts(where: {authorUid: {eq: $userId}}) {
    id, text, createdAt
  }
}

از استفاده از سطح دسترسی USER بدون فیلتر خودداری کنید

همانطور که چندین بار در راهنما مورد بحث قرار گرفت، سطوح دسترسی اصلی مانند USER ، USER_ANON ، USER_EMAIL_VERIFIED خطوط پایه و نقطه شروع برای بررسی مجوزها هستند که باید با فیلترها و عبارات بهبود یابند. استفاده از این سطوح بدون فیلتر یا عبارت مربوطه که بررسی می‌کند کدام کاربر درخواست را انجام می‌دهد، اساساً معادل استفاده از سطح PUBLIC است.

# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
  documents {
    id
    title
    text
  }
}

از استفاده از سطح دسترسی PUBLIC یا USER برای نمونه سازی خودداری کنید

برای سرعت بخشیدن به توسعه، تنظیم همه عملیات روی سطح دسترسی PUBLIC یا سطح دسترسی USER بدون پیشرفت بیشتر برای مجاز کردن همه عملیات و به شما امکان تست سریع کدتان می تواند وسوسه انگیز باشد.

وقتی نمونه‌سازی اولیه را به این روش انجام دادید، از NO_ACCESS به مجوز آماده تولید با سطوح PUBLIC و USER تغییر دهید. با این حال، آنها را به عنوان PUBLIC یا USER بدون اضافه کردن منطق اضافی همانطور که در این راهنما نشان داده شده است، مستقر نکنید.

# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
  post: post_delete(
    id: $id,
  )
}

برای تأیید برنامه Firebase App Check استفاده کنید

احراز هویت و مجوز از اجزای حیاتی امنیت Data Connect هستند. احراز هویت و مجوز همراه با تأیید برنامه یک راه حل امنیتی بسیار قوی را ایجاد می کند.

با تأیید از طریق Firebase App Check ، دستگاه‌هایی که برنامه شما را اجرا می‌کنند از یک برنامه یا ارائه‌دهنده گواهی دستگاه استفاده می‌کنند که تأیید می‌کند عملیات Data Connect از برنامه معتبر شما و درخواست‌ها از یک دستگاه معتبر و دستکاری نشده سرچشمه می‌گیرد. این تأییدیه به هر درخواستی که برنامه شما از Data Connect می کند پیوست می شود.

برای آشنایی با نحوه فعال کردن App Check for Data Connect و گنجاندن SDK سرویس گیرنده آن در برنامه، نگاهی به نمای کلی App Check بیندازید.

سطوح احراز هویت برای دستورالعمل @auth(level)

جدول زیر تمام سطوح دسترسی استاندارد و معادل های CEL آنها را فهرست می کند. سطوح احراز هویت از گسترده به باریک فهرست شده است - هر سطح شامل تمام کاربرانی است که با سطوح زیر مطابقت دارند.

سطح تعریف
PUBLIC این عملیات می تواند توسط هر کسی با یا بدون احراز هویت اجرا شود.

ملاحظات: داده ها می توانند توسط هر کاربری خوانده یا اصلاح شوند. Firebase این سطح از مجوز را برای داده‌های قابل مرور عمومی مانند فهرست‌های محصول یا رسانه توصیه می‌کند. نمونه ها و جایگزین های بهترین عمل را ببینید.

معادل @auth(expr: "true")

فیلترها و عبارات @auth را نمی توان در ترکیب با این سطح دسترسی استفاده کرد. چنین عباراتی با خطای 400 درخواست بد ناموفق خواهد بود.
USER_ANON هر کاربر شناسایی شده، از جمله کاربرانی که به طور ناشناس با Firebase Authentication وارد سیستم شده اند، مجاز به انجام پرس و جو یا جهش هستند.

توجه: USER_ANON ابر مجموعه ای از USER است.

ملاحظات: توجه داشته باشید که باید به دقت جستارها و جهش های خود را برای این سطح از مجوز طراحی کنید. این سطح به کاربر اجازه می‌دهد به‌صورت ناشناس وارد سیستم شود (ورود خودکار فقط به دستگاه کاربر مرتبط است) با Authentication ، و به تنهایی بررسی‌های دیگری را انجام نمی‌دهد، مثلاً اینکه آیا داده‌ها به کاربر تعلق دارند یا خیر. نمونه ها و جایگزین های بهترین عمل را ببینید.

از آنجایی که جریان های ورود ناشناس Authentication یک uid صادر می کند، سطح USER_ANON معادل است
@auth(expr: "auth.uid != nil")
USER هر کاربری که با Firebase Authentication وارد شده باشد، مجاز به انجام پرس و جو یا جهش است به جز کاربران ناشناس ورود به سیستم.

ملاحظات: توجه داشته باشید که باید به دقت جستارها و جهش های خود را برای این سطح از مجوز طراحی کنید. این سطح فقط بررسی می‌کند که کاربر با Authentication وارد شده باشد، و به تنهایی بررسی‌های دیگری را انجام نمی‌دهد، مثلاً اینکه آیا داده‌ها متعلق به کاربر است یا خیر. نمونه ها و جایگزین های بهترین عمل را ببینید.

معادل @auth(expr: "auth.uid != nil && auth.token.firebase.sign_in_provider != 'anonymous'")"
USER_EMAIL_VERIFIED هر کاربری که با Firebase Authentication با آدرس ایمیل تایید شده وارد شده باشد، مجاز به انجام پرس و جو یا جهش است.

ملاحظات: از آنجایی که تأیید ایمیل با استفاده از Authentication انجام می‌شود، بر اساس یک روش Authentication قوی‌تر است، بنابراین این سطح امنیت بیشتری را در مقایسه با USER یا USER_ANON فراهم می‌کند. این سطح فقط بررسی می کند که کاربر با Authentication با یک ایمیل تأیید شده وارد شده باشد و به تنهایی بررسی های دیگری را انجام نمی دهد، مثلاً اینکه آیا داده ها متعلق به کاربر است یا خیر. نمونه ها و جایگزین های بهترین عمل را ببینید.

معادل @auth(expr: "auth.uid != nil && auth.token.email_verified")"
NO_ACCESS این عملیات را نمی توان خارج از زمینه مدیریت SDK اجرا کرد.

معادل @auth(expr: "false")

مرجع CEL برای @auth(expr) و @check(expr)

همانطور که در نمونه‌های دیگر این راهنما نشان داده شده است، می‌توانید و باید از عبارات تعریف شده در Common Expression Language (CEL) برای کنترل مجوز برای Data Connect با استفاده از دستورالعمل‌های @auth(expr:) و @check استفاده کنید.

این بخش نحو CEL مربوط به ایجاد عبارات برای این دستورالعمل ها را پوشش می دهد.

اطلاعات مرجع کامل برای CEL در مشخصات CEL ارائه شده است.

متغیرهای آزمایشی در پرس و جوها و جهش‌ها تصویب شدند

نحو @auth(expr) به شما امکان می دهد به متغیرهای جستجو و جهش دسترسی داشته باشید و آنها را آزمایش کنید.

برای مثال، می‌توانید یک متغیر عملیاتی، مانند $status با استفاده از vars.status اضافه کنید.

mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")

داده های موجود برای عبارات

هر دو عبارت @auth(expr:) و @check(expr:) CEL می توانند موارد زیر را ارزیابی کنند:

  • request.operationName
  • vars (نام مستعار request.variables )
  • auth (مستعار request.auth )

علاوه بر این، عبارات @check(expr:) می توانند ارزیابی کنند:

  • this (مقدار فیلد فعلی)

شی request.operationName

شی request.operarationName نوع عملیات، پرس و جو یا جهش را ذخیره می کند.

شی vars

آبجکت vars به ​​عبارات شما اجازه می دهد تا به تمام متغیرهای ارسال شده در پرس و جو یا جهش شما دسترسی داشته باشند.

می توانید از vars.<variablename> در یک عبارت به عنوان نام مستعار برای request.variables.<variablename> :

# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")

auth

Authentication کاربرانی را که درخواست دسترسی به داده‌های شما را دارند شناسایی می‌کند و آن اطلاعات را به عنوان یک شی که می‌توانید در عبارات خود بر روی آن بسازید، ارائه می‌کند.

در فیلترها و عبارات خود، می توانید auth به عنوان نام مستعار request.auth استفاده کنید.

شی auth حاوی اطلاعات زیر است:

  • uid : یک شناسه کاربری منحصر به فرد که به کاربر درخواست کننده اختصاص داده می شود.
  • token : نقشه ای از مقادیر جمع آوری شده توسط Authentication .

برای جزئیات بیشتر در مورد محتوای auth.token به داده ها در نشانه های auth مراجعه کنید

this الزام آور

اتصال this به فیلدی که دستور @check به آن پیوست شده است ارزیابی می شود. در یک مورد اساسی، ممکن است نتایج پرس و جوی تک ارزشی را ارزیابی کنید.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    ) {
      # Check if the user has the editor role for the movie. `this` is the string value of `role`.
      # If the parent moviePermission is null, the @check will also fail automatically.
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

اگر فیلد برگشتی چندین بار رخ دهد زیرا هر اجدادی یک لیست است، هر رخداد با this کران به هر مقدار آزمایش می شود.

برای هر مسیر معین، اگر یک جد null یا [] باشد، به فیلد دسترسی پیدا نمی‌کند و ارزیابی CEL برای آن مسیر نادیده گرفته می‌شود. به عبارت دیگر، ارزیابی تنها زمانی صورت می‌گیرد this null یا غیر null باشد، اما هرگز undefined .

هنگامی که فیلد به خودی خود یک لیست یا شی است، this همان ساختار (شامل همه نزول های انتخاب شده در مورد اشیا) پیروی می کند، همانطور که در مثال زیر نشان داده شده است.

mutation UpdateMovieTitle2($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query {
    moviePermissions( # Now we query for a list of all matching MoviePermissions.
      where: {movieId: {eq: $movieId}, userId: {eq_expr: "auth.uid"}}
    # This time we execute the @check on the list, so `this` is the list of objects.
    # We can use the `.exists` macro to check if there is at least one matching entry.
    ) @check(expr: "this.exists(p, p.role == 'editor')", message: "You must be an editor of this movie to update title") {
      role
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

نحو عبارت پیچیده

می توانید با ترکیب کردن با && و || عبارات پیچیده تری بنویسید اپراتورها

mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")

بخش زیر تمام اپراتورهای موجود را توضیح می دهد.

اپراتورها و تقدم عملگر

از جدول زیر به عنوان مرجع برای عملگرها و اولویت مربوط به آنها استفاده کنید.

عبارات دلخواه a و b ، یک فیلد f و یک شاخص i داده می شود.

اپراتور توضیحات انجمنی
a[i] a() af فهرست، تماس، دسترسی به میدان چپ به راست
!a -a نفی واحد راست به چپ
a/ba%ba*b عملگرهای ضربی چپ به راست
a+b ab اپراتورهای افزودنی چپ به راست
a>b a>=b a<b a<=b عملگرهای رابطه ای چپ به راست
a in b وجود در فهرست یا نقشه چپ به راست
type(a) == t مقایسه نوع، جایی که t می تواند bool، int، float، عدد، رشته، فهرست، نقشه، مهر زمانی یا مدت باشد. چپ به راست
a==ba!=b عملگرهای مقایسه چپ به راست
a && b AND مشروط چپ به راست
a || b OR مشروط چپ به راست
a ? true_value : false_value بیان سه تایی چپ به راست

داده ها در توکن های احراز هویت

شی auth.token ممکن است حاوی مقادیر زیر باشد:

میدان توضیحات
email آدرس ایمیل مرتبط با حساب، در صورت وجود.
email_verified true اگر کاربر تأیید کرده باشد که به آدرس email دسترسی دارد. برخی از ارائه دهندگان به طور خودکار آدرس های ایمیل خود را تأیید می کنند.
phone_number شماره تلفن مرتبط با حساب، در صورت وجود.
name نام نمایشی کاربر، در صورت تنظیم.
sub UID Firebase کاربر. این در یک پروژه منحصر به فرد است.
firebase.identities فرهنگ لغت همه هویت هایی که با حساب این کاربر مرتبط هستند. کلیدهای فرهنگ لغت می توانند یکی از موارد زیر باشند: email ، phone ، google.com ، facebook.com ، github.com ، twitter.com . مقادیر فرهنگ لغت آرایه‌هایی از شناسه‌های منحصربه‌فرد برای هر ارائه‌دهنده هویت مرتبط با حساب است. برای مثال، auth.token.firebase.identities["google.com"][0] حاوی اولین شناسه کاربری Google مرتبط با حساب است.
firebase.sign_in_provider ارائه‌دهنده ورود به سیستم برای دریافت این رمز استفاده می‌کند. می تواند یکی از رشته های زیر باشد: custom ، password ، phone ، anonymous ، google.com ، facebook.com ، github.com ، twitter.com .
firebase.tenant شناسه مستاجر مرتبط با حساب، در صورت وجود. به عنوان مثال، tenant2-m6tyz

فیلدهای اضافی در توکن های JWT ID

همچنین می توانید به فیلدهای auth.token زیر دسترسی داشته باشید:

ادعاهای توکن سفارشی
alg الگوریتم "RS256"
iss صادر کننده آدرس ایمیل حساب سرویس پروژه شما
sub موضوع آدرس ایمیل حساب سرویس پروژه شما
aud مخاطب "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat صادر شده در زمان زمان فعلی، در ثانیه از دوران یونیکس
exp زمان انقضا زمان، بر حسب ثانیه از دوره یونیکس، که در آن توکن منقضی می‌شود. می تواند حداکثر 3600 ثانیه دیرتر از iat باشد.
توجه: این فقط زمانی را کنترل می کند که خود توکن سفارشی منقضی شود. اما هنگامی که کاربر را با استفاده از signInWithCustomToken() وارد سیستم کردید، تا زمانی که جلسه آنها باطل شود یا کاربر از سیستم خارج نشود، وارد دستگاه می‌شوند.
<claims> (اختیاری) ادعای سفارشی اختیاری برای گنجاندن در نشانه، که می‌تواند از طریق auth.token (یا request.auth.token ) در عبارات قابل دسترسی باشد. برای مثال، اگر یک ادعای سفارشی adminClaim ایجاد کنید، می‌توانید با auth.token.adminClaim به آن دسترسی داشته باشید.

بعدش چی؟