‫۴ سال و ۵ ماه قبل، شنبه ۲۳ فروردین ۱۳۹۹، ساعت ۰۴:۰۹
validateProperty یک خاصیت را تعیین اعتبار می‌کند، اما برای تطابق پسوردها، نیاز به تعیین اعتبار دو خاصیت را با هم دارد. به همین جهت برای مثال می‌توان پارامتر چهارمی را به نام correspond، در اینجا اضافه کرد تا فیلد متناظر با آن‌را هم مشخص کند:
  renderInput(name, label, type = "text", correspond) {
    const { data, errors } = this.state;
    return (
      <Input
        name={name}
        type={type}
        label={label}
        value={data[name]}
        onChange={this.handleChange}
        error={errors[name]}
        correspond={correspond}
      />
    );
  }
بعد برای نمونه، تعریف فرم ثبت نام، به صورت زیر تغییر می‌کند که در آن confirmPassword هم اضافه شده و فیلد متناظر با آن، password است:
        <form onSubmit={this.handleSubmit}>
          {this.renderInput("username", "Username")}
          {this.renderInput("password", "Password", "password")}
          {this.renderInput(
            "confirmPassword",
            "Confirm Password",
            "password",
            "password"
          )}
          {this.renderInput("name", "Name")}
          {this.renderButton("Register")}
        </form>
در این حالت، داده‌های فرم و اعتبارسنجی‌های آن، به صورت زیر تعریف می‌شوند:
  state = {
    data: { username: "", password: "", name: "", confirmPassword: "" },
    errors: {},
  };

  schema = {
    username: Joi.string()
      .required()
      .email({ minDomainSegments: 2, tlds: { allow: ["com", "net", "info"] } })
      .label("Username"),
    password: Joi.string().required().min(5).label("Password"),
    name: Joi.string().required().label("Name"),
    confirmPassword: Joi.any().valid(Joi.ref("password")).required().messages({
      "any.only": "با رمز عبور مطابقت ندارد",
    }),
  };
و در آخر متد validateProperty بر اساس attribute سفارشی اضافه شده به نام correspond، در صورت وجود و تعریف آن، یک خاصیت پویا را به شیء داده‌های ورودی و همچنین شیء schema اضافه می‌کند که این‌ها سبب خواهند شد تا اینبار اعتبارسنجی بر روی دو فیلد صورت گیرد:
  validateProperty = ({ name, value, attributes }) => {
    const userInputObject = { [name]: value };
    const schemaMap = { [name]: this.schema[name] };

    if (attributes.correspond) {
      const correspondFieldName = attributes.correspond.value;
      userInputObject[correspondFieldName] = this.state.data[
        correspondFieldName
      ];
      schemaMap[correspondFieldName] = this.schema[correspondFieldName];
    }

    const propertySchema = Joi.object(schemaMap);
    const { error } = propertySchema.validate(userInputObject, {
      abortEarly: true,
    });
    return error ? error.details[0].message : null;
  };
‫۴ سال و ۵ ماه قبل، شنبه ۲۳ فروردین ۱۳۹۹، ساعت ۰۱:۱۱
همان روش messages را که عنوان کردید برای نمایش خطاها در نگارش‌های جدیدتر استفاده می‌شود. کلیدهای آن‌را هم اگر خواستید پیدا کنید روش آن به صورت زیر است:
firstName: Joi.string().min(5).max(10).required().error(errors => {
    errors.forEach(err => {
      switch (err.type) {
        case "any.empty":
          err.message = "Value should not be empty!";
          break;
        case "string.min":
          err.message = `Value should have at least ${err.context.limit} characters!`;
          break;
        case "string.max":
          err.message = `Value should have at most ${err.context.limit} characters!`;
          break;
        default:
          break;
      }
    });
    return errors;
  }),
‫۴ سال و ۵ ماه قبل، شنبه ۲۳ فروردین ۱۳۹۹، ساعت ۰۰:۴۵
این موارد را آزمایش کنید:
password: Joi.string().min(3).max(15).required(),
password_confirmation: Joi.any().valid(Joi.ref('password')).required().options({ language: { any: { allowOnly: 'must match password' } } })
و یا
confirmPassword: Joi.string().required().valid(Joi.ref('password')).options({
  language: {
    any: {
      allowOnly: '!!Passwords do not match',
    }
  } 
})
‫۴ سال و ۵ ماه قبل، جمعه ۲۲ فروردین ۱۳۹۹، ساعت ۱۲:۰۲
- مقدار AccessTokenExpirationMinutes را در فایل تنظیمات برنامه تغییر دهید.
- مفهوم refresh token در اینجا شبیه به پیاده سازی sliding expiration برای کوکی‌ها است. اطلاعات بیشتر: «معرفی JSON Web Token» + مثال به روز رسانی خودکار توکن منقضی شده با یک تایمر سمت کلاینت، در سری «احراز هویت و اعتبارسنجی کاربران در برنامه‌های Angular» عمیق‌تر بررسی شده‌است. 
‫۴ سال و ۵ ماه قبل، دوشنبه ۱۸ فروردین ۱۳۹۹، ساعت ۱۴:۴۶
استفاده از آنتی فورجری توکن در برنامه‌های کلاینت جاوا اسکریپتی؛ مانند «افزودن و اعتبارسنجی خودکار Anti-Forgery Tokens در برنامه‌های Angular مبتنی بر ASP.NET Core»
‫۴ سال و ۵ ماه قبل، دوشنبه ۱۸ فروردین ۱۳۹۹، ساعت ۰۶:۳۳
Docker در اصل یک برنامه‌ی لینوکسی هست که بعدها به ویندوز و Mac هم منتقل شد و containers آن بر فراز هسته‌ی لینوکس اجرا می‌شوند (در سایر سیستم عامل‌ها یک Linux virtual machine برای آن تهیه شده). ویندوز یک سیستم عامل هست که تشکیل شده از کتابخانه‌ها و برنامه‌های کاربردی که بر فراز یک هسته اجرا می‌شود. در قسمت سوم، این مورد بیشتر بحث شده: «چرا حجم Image مخصوص .NET Core نگارش nanoserver آن حدود 800 مگابایت است؟»
‫۴ سال و ۵ ماه قبل، چهارشنبه ۱۳ فروردین ۱۳۹۹، ساعت ۱۸:۴۱
- آیا FindByEmailAsync از ایمیل نرمال سازی شده استفاده می‌کند؟ بله.
- آیا CustomNormalizer ای که در اینجا نوشته شده (با فرض معرفی به سیستم)، _ را هم نرمال سازی می‌کند؟ خیر. با این آزمایش‌ها.
+ همانطور که در نکته‌ی ارتقاء به نگارش 3 عنوان شد، نرمال سازی ایمیل و نام کاربری از هم جدا شده‌اند. اگر می‌خواهید نرمال سازی ایمیل، به نام کاربری هم اعمال شود، باید کلاس سفارشی تهیه شده را تغییر دهید.