Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auth-pages): allow translation for required input field messages #5868

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/cold-emus-visit.md
@@ -0,0 +1,12 @@
---
"@refinedev/antd": minor
"@refinedev/chakra-ui": minor
"@refinedev/mui": minor
"@refinedev/live-previews": minor
aliemir marked this conversation as resolved.
Show resolved Hide resolved
---

feat: add message prop for required auth input fields for the above packages.

Now you can provide custom required messages with translate feature for all auth input fields(Login, register, forget password,update password).

Resolves #[5855](https://github.com/refinedev/refine/issues/5855)
141 changes: 141 additions & 0 deletions documentation/blog/2024-04-24-node-uuid.md
@@ -0,0 +1,141 @@
---
title: 4 Ways to Generate UUIDs in Node.js
description: We'll explore how UUIDs work in Node.js and how they can help keep data distinct and make your projects easier to scale.
slug: node-js-uuid
authors: necati
tags: [dev-tools]
image: https://refine.ams3.cdn.digitaloceanspaces.com/blog/2024-04-24-node-uuid/social.png
hide_table_of_contents: false
---

## Introduction

In software development, it's important to make sure that each piece of data is unique to prevent overlaps and errors. Universally Unique Identifiers, or UUIDs, help solve this problem by giving each item a unique label. They’re becoming crucial as more systems and services link over various networks. They make sure every piece of data remains unique, preventing any overlaps and errors.

In this blog post, we'll look at how UUIDs work in Node.js and how they can help keep data distinct and make your projects easier to scale.

Steps we'll cover:

- [What is a UUID?](#what-is-a-uuid)
- [Why Use UUIDs in Your Node.js Projects?](#why-use-uuids-in-your-nodejs-projects)
- [How to Generate UUIDs](#how-to-generate-uuids)

## What is a UUID?

A UUID is a 128-bit number used to uniquely label information in computer systems, as defined in RFC 4122. There are several versions, but the ones we often use are UUIDv1 and UUIDv4. UUIDv1 generates IDs based on the time they're created and includes this timestamp. It’s useful because you can trace when and where it was generated, which can help in some debugging scenarios.

On the other hand, UUIDv4 is totally random, providing a much higher level of security due to its unpredictability—ideal for sensitive applications where privacy is a concern.

Each type serves distinct purposes, catering to the specific needs of data identification and security in software development.

## Why Use UUIDs in Your Node.js Projects?

Using UUIDs in Node.js enhances data uniqueness and integrity, making it ideal for distributed systems and preventing ID collisions. It facilitates data merging from different sources due to the guaranteed uniqueness of each identifier. Additionally, UUIDs increase security by making it difficult to predict IDs, protecting against unauthorized data access. They also allow for more flexible database schema design, enabling agile development and easier database migrations by handling IDs at the application level.

Integrating UUIDs in our Node.js applications helps us ensure that every data entry is unique—this is vital for systems where multiple instances or databases need to merge or sync without conflicts. It also boosts our system's security, as the randomness of UUIDv4 makes it tough for anyone to guess the ID sequences, protecting against some forms of cyber attacks. Plus, using UUIDs lets us be more agile with our database schema, since IDs are handled at the application level, making it easier to evolve our database without messy migrations.

## How to Generate UUID'S?

To generate UUIDs in a Node.js environment, you can use different methods and packages depending on your specific needs and preferences. Below, I’ll guide you through three different approaches: using the built-in Node.js [`crypto`](https://nodejs.org/docs/latest-v14.x/api/crypto.html#crypto_crypto_randomuuid_options) module, the popular [`uuid`](https://github.com/uuidjs/uuid) npm package, and the [`nanoid`](https://github.com/ai/nanoid) npm package.

### 1. Using Node.js Crypto Module

Node.js includes a built-in module called `crypto` that can be used to generate UUIDs, specifically UUID v4, which are random:

```javascript
const crypto = require("crypto");

let uuid = crypto.randomUUID();
```

This function utilizes the `crypto` module's `randomUUID` method to generate random bytes, which are then formatted into a UUID v4 compliant formatr.

When you log, you can get similar like the following:

```
00a1dv45-dx19-2301-2471-223932594567
```

### 2. UUID npm Package

The `uuid` npm package is a very popular choice for generating UUIDs in Node.js applications. It supports multiple versions of UUIDs:

#### Installation

```bash
npm install uuid
```

#### Usage

```javascript
const { v4: uuidv4 } = require("uuid");

// Generate a UUID v4
const uuid = uuidv4();
console.log(`UUID: ${uuid}`);
// ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'
```

This package provides simple, straightforward methods for generating UUIDs and supports UUID versions 1, 3, 4, and 5.

#### API table

| | | |
| -------------------------------------------------- | -------------------------------------------- | ----------------- |
| [`uuid.NIL`](#uuidnil) | The nil UUID string (all zeros) | New in `uuid@8.3` |
| [`uuid.parse()`](#uuidparsestr) | Convert UUID string to array of bytes | New in `uuid@8.3` |
| [`uuid.stringify()`](#uuidstringifyarr-offset) | Convert array of bytes to UUID string | New in `uuid@8.3` |
| [`uuid.v1()`](#uuidv1options-buffer-offset) | Create a version 1 (timestamp) UUID | |
| [`uuid.v3()`](#uuidv3name-namespace-buffer-offset) | Create a version 3 (namespace w/ MD5) UUID | |
| [`uuid.v4()`](#uuidv4options-buffer-offset) | Create a version 4 (random) UUID | |
| [`uuid.v5()`](#uuidv5name-namespace-buffer-offset) | Create a version 5 (namespace w/ SHA-1) UUID | |
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `uuid@8.3` |
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `uuid@8.3` |

### 3. Nano ID Package

Nano ID is a tiny, secure URL-friendly unique string ID generator for JavaScript, which can be used as an alternative to UUIDs. It offers a similar level of uniqueness and randomness and is a great choice when shorter IDs are needed:

#### Installation

```bash
npm install nanoid
```

#### Usage

```javascript
const { nanoid } = require("nanoid");

// Generate a Nano ID
const id = nanoid();
console.log(`Nano ID: ${id}`);
```

Nano ID generates URL-friendly IDs by default, which are shorter and more memory-efficient than UUIDs.

Each of these methods provides unique identifiers suitable for various applications, from managing database keys to tracking unique user sessions. Choose the method that best fits your project’s requirements.

### 4. Bonus: short-uuid

[short-uuid](https://github.com/oculus42/short-uuid) simplifies the generation and translation of UUIDs into shorter or alternative formats, and vice versa.

The latest version, 4.0.0, brings some significant changes like improved error handling, modern ECMAScript support, and consistent-length value generation. This means you can now easily handle UUIDs in a more efficient and error-free manner.

To get started, you just need to install the library and use its simple API to generate or translate UUIDs. It's particularly handy when you need shorter identifiers for your application, like in URLs or database keys.

```
const short = require('short-uuid');

// Quick start with flickrBase58 format
short.generate(); // Example: 73WakrfVbNJBaAmhQtEeDv
```

- `short-uuid` takes RFC4122 v4-compliant UUIDs and translates them into shorter formats.
- Version 4.0.0 ensures consistent-length values unless otherwise specified, achieved by padding with the first character in the alphabet.
- Translators enable conversion back and forth between RFC compliant UUIDs and shortened formats.

## Conclusion

UUIDs are essential for ensuring data integrity and uniqueness in distributed systems. They provide a reliable way to label data and prevent ID collisions, making them ideal for applications that require secure and scalable data management. By integrating UUIDs into your Node.js projects, you can enhance your system's security, flexibility, and performance, ensuring that your data remains distinct and secure across various platforms and networks.
15 changes: 11 additions & 4 deletions documentation/docs/partials/_partial-translation-file-de.md
Expand Up @@ -11,7 +11,9 @@
"password": "Passwort"
},
"errors": {
"validEmail": "Ungültige E-Mail-Adresse"
"validEmail": "Ungültige E-Mail-Adresse",
"requiredEmail": "E-Mail ist erforderlich",
"requiredPassword": "Passwort wird benötigt"
},
"buttons": {
"submit": "Anmeldung",
Expand All @@ -26,7 +28,8 @@
"email": "Email"
},
"errors": {
"validEmail": "Ungültige E-Mail-Adresse"
"validEmail": "Ungültige E-Mail-Adresse",
"requiredEmail": "E-Mail ist erforderlich"
},
"buttons": {
"submit": "Anweisungen zum Zurücksetzen senden"
Expand All @@ -39,7 +42,9 @@
"password": "Passwort"
},
"errors": {
"validEmail": "Ungültige E-Mail-Adresse"
"validEmail": "Ungültige E-Mail-Adresse",
"requiredEmail": "E-Mail ist erforderlich",
"requiredPassword": "Passwort wird benötigt"
},
"buttons": {
"submit": "Registrieren",
Expand All @@ -53,7 +58,9 @@
"confirmPassword": "Bestätige neues Passwort"
},
"errors": {
"confirmPasswordNotMatch": "Passwörter stimmen nicht überein"
"confirmPasswordNotMatch": "Passwörter stimmen nicht überein",
"requiredPassword": "Passwort wird benötigt",
"requiredConfirmPassword": "Das Feld „Passwort bestätigen“ ist erforderlich"
},
"buttons": {
"submit": "Aktualisieren"
Expand Down
15 changes: 11 additions & 4 deletions documentation/docs/partials/_partial-translation-file-en.md
Expand Up @@ -11,7 +11,9 @@
"password": "Password"
},
"errors": {
"validEmail": "Invalid email address"
"validEmail": "Invalid email address",
"requiredEmail": "Email is required",
"requiredPassword": "Password is required"
},
"buttons": {
"submit": "Login",
Expand All @@ -26,7 +28,8 @@
"email": "Email"
},
"errors": {
"validEmail": "Invalid email address"
"validEmail": "Invalid email address",
"requiredEmail": "Email is required"
},
"buttons": {
"submit": "Send reset instructions"
Expand All @@ -39,7 +42,9 @@
"password": "Password"
},
"errors": {
"validEmail": "Invalid email address"
"validEmail": "Invalid email address",
"requiredEmail": "Email is required",
"requiredPassword": "Password is required"
},
"buttons": {
"submit": "Register",
Expand All @@ -53,7 +58,9 @@
"confirmPassword": "Confirm new password"
},
"errors": {
"confirmPasswordNotMatch": "Passwords do not match"
"confirmPasswordNotMatch": "Passwords do not match",
"requiredPassword": "Password required",
"requiredConfirmPassword": "Confirm password is required"
},
"buttons": {
"submit": "Update"
Expand Down
Expand Up @@ -112,7 +112,13 @@ export const ForgotPasswordPage: React.FC<ResetPassworProps> = ({
name="email"
label={translate("pages.forgotPassword.fields.email", "Email")}
rules={[
{ required: true },
{
required: true,
message: translate(
"pages.forgotPassword.errors.requiredEmail",
"Email is required",
),
},
{
type: "email",
message: translate(
Expand Down
18 changes: 16 additions & 2 deletions packages/antd/src/components/pages/auth/components/login/index.tsx
Expand Up @@ -163,7 +163,13 @@ export const LoginPage: React.FC<LoginProps> = ({
name="email"
label={translate("pages.login.fields.email", "Email")}
rules={[
{ required: true },
{
required: true,
message: translate(
"pages.login.errors.requiredEmail",
"Email is required",
),
},
{
type: "email",
message: translate(
Expand All @@ -181,7 +187,15 @@ export const LoginPage: React.FC<LoginProps> = ({
<Form.Item
name="password"
label={translate("pages.login.fields.password", "Password")}
rules={[{ required: true }]}
rules={[
{
required: true,
message: translate(
"pages.login.errors.requiredPassword",
"Password is required",
),
},
]}
>
<Input
type="password"
Expand Down
Expand Up @@ -157,7 +157,13 @@ export const RegisterPage: React.FC<RegisterProps> = ({
name="email"
label={translate("pages.register.email", "Email")}
rules={[
{ required: true },
{
required: true,
message: translate(
"pages.register.errors.requiredEmail",
"Email is required",
),
},
{
type: "email",
message: translate(
Expand All @@ -175,7 +181,15 @@ export const RegisterPage: React.FC<RegisterProps> = ({
<Form.Item
name="password"
label={translate("pages.register.fields.password", "Password")}
rules={[{ required: true }]}
rules={[
{
required: true,
message: translate(
"pages.register.errors.requiredPassword",
"Password is required",
),
},
]}
>
<Input type="password" placeholder="●●●●●●●●" size="large" />
</Form.Item>
Expand Down
Expand Up @@ -106,7 +106,15 @@ export const UpdatePasswordPage: React.FC<UpdatePasswordProps> = ({
"pages.updatePassword.fields.password",
"New Password",
)}
rules={[{ required: true }]}
rules={[
{
required: true,
message: translate(
"pages.updatePassword.errors.requiredPassword",
"Password is required",
),
},
]}
style={{ marginBottom: "12px" }}
>
<Input type="password" placeholder="●●●●●●●●" size="large" />
Expand All @@ -122,6 +130,10 @@ export const UpdatePasswordPage: React.FC<UpdatePasswordProps> = ({
rules={[
{
required: true,
message: translate(
"pages.updatePassword.errors.requiredConfirmPassword",
"Confirm password is required",
),
},
({ getFieldValue }) => ({
validator(_, value) {
Expand Down
Expand Up @@ -110,7 +110,10 @@ export const ForgotPasswordPage: React.FC<ForgotPasswordProps> = ({
id="email"
type="text"
{...register("email", {
required: true,
required: translate(
"pages.forgotPassword.errors.requiredEmail",
"Email is required",
),
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: translate(
Expand Down
Expand Up @@ -155,7 +155,10 @@ export const LoginPage: React.FC<LoginProps> = ({
placeholder="Email"
type="text"
{...register("email", {
required: true,
required: translate(
"pages.login.errors.requiredEmail",
"Email is required",
),
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: translate(
Expand All @@ -177,7 +180,10 @@ export const LoginPage: React.FC<LoginProps> = ({
type="password"
placeholder="Password"
{...register("password", {
required: true,
required: translate(
"pages.login.errors.requiredPassword",
"Password is required",
),
})}
/>
<FormErrorMessage>{`${errors.password?.message}`}</FormErrorMessage>
Expand Down