mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-03-14 02:32:00 +08:00
Compare commits
3 Commits
fix/auth-c
...
fix/authen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fce5545b60 | ||
|
|
19f5885e62 | ||
|
|
5c771c806d |
@@ -2,7 +2,7 @@ import Cookies from 'js-cookie';
|
||||
import type { FormEvent } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { httpPost } from '../../lib/http';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
|
||||
type EmailLoginFormProps = {
|
||||
isDisabled?: boolean;
|
||||
@@ -34,7 +34,11 @@ export function EmailLoginForm(props: EmailLoginFormProps) {
|
||||
|
||||
// Log the user in and reload the page
|
||||
if (response?.token) {
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.reload();
|
||||
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
|
||||
@@ -70,7 +70,11 @@ export function GitHubButton(props: GitHubButtonProps) {
|
||||
|
||||
localStorage.removeItem(GITHUB_REDIRECT_AT);
|
||||
localStorage.removeItem(GITHUB_LAST_PAGE);
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.href = redirectUrl;
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
||||
@@ -69,7 +69,11 @@ export function GoogleButton(props: GoogleButtonProps) {
|
||||
|
||||
localStorage.removeItem(GOOGLE_REDIRECT_AT);
|
||||
localStorage.removeItem(GOOGLE_LAST_PAGE);
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.href = redirectUrl;
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { Spinner } from '../ReactIcons/Spinner.tsx';
|
||||
import { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';
|
||||
@@ -69,7 +69,11 @@ export function LinkedInButton(props: LinkedInButtonProps) {
|
||||
|
||||
localStorage.removeItem(LINKEDIN_REDIRECT_AT);
|
||||
localStorage.removeItem(LINKEDIN_LAST_PAGE);
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.href = redirectUrl;
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type FormEvent, useEffect, useState } from 'react';
|
||||
import { httpPost } from '../../lib/http';
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
|
||||
export function ResetPasswordForm() {
|
||||
const [code, setCode] = useState('');
|
||||
@@ -37,7 +37,7 @@ export function ResetPasswordForm() {
|
||||
newPassword: password,
|
||||
confirmPassword: passwordConfirm,
|
||||
code,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (error?.message) {
|
||||
@@ -53,7 +53,11 @@ export function ResetPasswordForm() {
|
||||
}
|
||||
|
||||
const token = response.token;
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.href = '/';
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import Cookies from 'js-cookie';
|
||||
import { httpPost } from '../../lib/http';
|
||||
import { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { Spinner } from '../ReactIcons/Spinner';
|
||||
import { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';
|
||||
|
||||
@@ -26,7 +26,11 @@ export function TriggerVerifyAccount() {
|
||||
return;
|
||||
}
|
||||
|
||||
setAuthToken(response.token);
|
||||
Cookies.set(TOKEN_COOKIE_NAME, response.token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
window.location.href = '/';
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { TOKEN_COOKIE_NAME, removeAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
|
||||
export function logout() {
|
||||
removeAuthToken();
|
||||
Cookies.remove(TOKEN_COOKIE_NAME, {
|
||||
path: '/',
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
|
||||
// Reloading will automatically redirect the user if required
|
||||
window.location.reload();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { type ChangeEvent, type FormEvent, useEffect, useRef, useState } from 'react';
|
||||
import { TOKEN_COOKIE_NAME, removeAuthToken } from '../../lib/jwt';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
|
||||
interface PreviewFile extends File {
|
||||
preview: string;
|
||||
@@ -128,7 +128,7 @@ export default function UploadProfilePicture(props: UploadProfilePictureProps) {
|
||||
|
||||
// Logout user if token is invalid
|
||||
if (data.status === 401) {
|
||||
removeAuthToken();
|
||||
Cookies.remove(TOKEN_COOKIE_NAME);
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Hateoas
|
||||
|
||||
HATEOAS is an acronym for <b>H</b>ypermedia <b>A</b>s <b>T</b>he <b>E</b>ngine <b>O</b>f <b>A</b>pplication <b>S</b>tate, it's the concept that when sending information over a RESTful API the document received should contain everything the client needs in order to parse and use the data i.e they don't have to contact any other endpoint not explicitly mentioned within the Document.
|
||||
HATEOAS is an acronym for <b>H</b>ypermedia <b>A</b>s <b>T</b>he <b>E</b>ngine <b>O</b>f <b>A</b>pplication <b>S</b>tate, it's the concept that when sending information over a RESTful API the document received should contain everything the client needs in order to parse and use the data i.e they don't have to contact any other endpoint not explicitly mentioned within the Document
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Oktane17: Designing Beautiful REST + JSON APIs (3:56 - 5:57)](https://youtu.be/MiOSzpfP1Ww?t=236)
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
# Quaternion
|
||||
|
||||
The **quaternion** is a complex number system that extends the concept of rotations in three dimensions. It involves four components: one real and three imaginary parts. Quaternions are used in game development for efficient and accurate calculations of rotations and orientation. They are particularly useful over other methods, such as Euler angles, due to their resistance to problems like Gimbal lock. Despite their complex nature, understanding and implementing quaternions can greatly enhance a game's 3D rotational mechanics and accuracy.
|
||||
|
||||
- [Understanding Quaternions](https://www.3dgep.com/understanding-quaternions/)
|
||||
- [Unity docs - Quaternions](https://docs.unity3d.com/ScriptReference/Quaternion.html)
|
||||
- [Quaternions and 3d rotation,explained interactively](https://youtu.be/zjMuIxRvygQ?si=ANmFr5k8JMUzBCUC)
|
||||
The **quaternion** is a complex number system that extends the concept of rotations in three dimensions. It involves four components: one real and three imaginary parts. Quaternions are used in game development for efficient and accurate calculations of rotations and orientation. They are particularly useful over other methods, such as Euler angles, due to their resistance to problems like Gimbal lock. Despite their complex nature, understanding and implementing quaternions can greatly enhance a game's 3D rotational mechanics and accuracy.
|
||||
@@ -1,5 +1,3 @@
|
||||
# Rust
|
||||
|
||||
**Rust** is a modern, open-source, multi-paradigm programming language designed for performance and safety, especially safe concurrency. It was initially designed by Mozilla Research as a language that can provide memory safety without garbage collection. Since then, it has gained popularity due to its features and performance that often compare favorably to languages like C++. Its rich type system and ownership model guarantee memory-safety and thread-safety while maintaining a high level of abstraction. Rust supports a mixture of imperative procedural, concurrent actor, object-oriented and pure functional styles.
|
||||
|
||||
[Learn Rust full tutorial](https://youtu.be/BpPEoZW5IiY?si=lyBbBPLXQ0HWdJNr
|
||||
**Rust** is a modern, open-source, multi-paradigm programming language designed for performance and safety, especially safe concurrency. It was initially designed by Mozilla Research as a language that can provide memory safety without garbage collection. Since then, it has gained popularity due to its features and performance that often compare favorably to languages like C++. Its rich type system and ownership model guarantee memory-safety and thread-safety while maintaining a high level of abstraction. Rust supports a mixture of imperative procedural, concurrent actor, object-oriented and pure functional styles.
|
||||
@@ -70,4 +70,4 @@ db.events.aggregate([
|
||||
|
||||
This query groups events by the day and year, providing a count of events for each day.
|
||||
|
||||
- [MongoDB Documentation Date](https://www.mongodb.com/docs/manual/reference/method/Date/)
|
||||
- [MongoDB Documentation Date](https://www.mongodb.com/docs/manual/reference/method/date/)
|
||||
@@ -1,36 +1,33 @@
|
||||
# MongoDB Analyzer
|
||||
# Analyzer
|
||||
|
||||
The MongoDB Analyzer for Visual Studio (VS) is a powerful development tool that helps you work with MongoDB by providing an integrated environment within your Visual Studio IDE. This add-on enhances your productivity and efficiency when developing applications with MongoDB, as it offers several benefits such as code assistance, syntax highlighting, IntelliSense support, and more.
|
||||
The Visual Studio (VS) Analyzer for MongoDB is a powerful development tool that helps you work with MongoDB by providing an integrated environment within your Visual Studio IDE. This add-on enhances your productivity and efficiency when developing applications with MongoDB, as it offers several benefits such as code assistance, syntax highlighting, IntelliSense support, and more.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Syntax Highlighting**: The MongoDB Analyzer provides syntax highlighting to help you quickly identify and understand different elements in your code, such as variables, operators, and functions.
|
||||
- **Syntax Highlighting**: The VS Analyzer provides syntax highlighting to help you quickly identify and understand different elements in your code, such as variables, operators, and functions.
|
||||
|
||||
- **IntelliSense Support**: IntelliSense is an intelligent code completion feature that predicts and suggests likely entries based on the context. It makes it easier to write queries by providing contextual suggestions based on your input.
|
||||
|
||||
- **Code Snippets**: This feature allows you to insert common MongoDB code patterns and functionalities directly into your code editor with just a few clicks. This can save you time and help maintain a consistent coding style across your project.
|
||||
|
||||
- **Query Profiling**: The MongoDB Analyzer allows you to profile and optimize MongoDB queries. By analyzing query performance, you can identify slow or problematic queries and make appropriate improvements to ensure better performance.
|
||||
- **Query Profiling**: The VS Analyzer allows you to profile and optimize MongoDB queries. By analyzing query performance, you can identify slow or problematic queries and make appropriate improvements to ensure better performance.
|
||||
|
||||
- **Debugging**: The Analyzer offers debugging support to help you identify and fix issues in your MongoDB queries and scripts, improving the overall reliability of your application.
|
||||
|
||||
- **Integrated Shell**: MongoDB Analyzer offers an integrated shell within Visual Studio that allows you to run MongoDB commands and queries directly within the IDE. This makes it more convenient to interact with your MongoDB instances and perform various tasks without switching between different tools.
|
||||
- **Integrated Shell**: VS Analyzer offers an integrated shell within Visual Studio that allows you to run MongoDB commands and queries directly within the IDE. This makes it more convenient to interact with your MongoDB instances and perform various tasks without switching between different tools.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To start using MongoDB Analyzer for Visual Studio, follow these steps:
|
||||
To start using the VS Analyzer for MongoDB, follow these steps:
|
||||
|
||||
- Download and install the [Visual Studio MongoDB Extension](https://marketplace.visualstudio.com/items?itemName=ms-ossdata.vscode-mongodb) from the Visual Studio Marketplace.
|
||||
|
||||
- Open your Visual Studio IDE and create a new project or open an existing one.
|
||||
|
||||
- Download and install the [MongoDB Analyzer as a NuGet package](https://www.nuget.org/packages/MongoDB.Analyzer/1.0.0) in Visual Studio from:
|
||||
- Add a reference to the MongoDB extension in your project by right-clicking on `References` and selecting `Add Package`.
|
||||
|
||||
- **Package Manager**: Click `Tools` > `NuGet Package Manager` > `Package Manager Console` and then execute this command: ```Install-Package MongoDB.Analyzer -Version 1.0.0```
|
||||
- **.NET CLI**: Click `View` > `Terminal` and then execute this command: ```dotnet add package MongoDB.Analyzer --version 1.0.0```
|
||||
- Search for `MongoDB` in the package manager window, and install the relevant packages for your project.
|
||||
|
||||
- Once installed, it will be added to your project’s Dependencies list, under Analyzers.
|
||||
- Once the extension is installed, you can access the MongoDB features through the `Extensions` menu in Visual Studio.
|
||||
|
||||
- After installing and once the analyzer has run, you’ll find all of the diagnostic warnings output to the Error List panel. As you start to inspect your code, you’ll also see that any unsupported expressions will be highlighted.
|
||||
|
||||
- Learn more about MongoDB Analyzer from the [official docs](https://www.mongodb.com/developer/languages/csharp/introducing-mongodb-analyzer-dotnet/).
|
||||
|
||||
With the MongoDB Analyzer for Visual Studio, you'll be able to write cleaner, faster, and more efficient code, making it an essential tool for any MongoDB developer.
|
||||
With the VS Analyzer for MongoDB, you'll be able to write cleaner, faster, and more efficient code, making it an essential tool for any MongoDB developer.
|
||||
|
||||
@@ -4,5 +4,5 @@ Routing is an essential concept in Single Page Applications (SPA). When your app
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [How to use Routing in React JS: A Comprehensive Guide. ](https://blog.logrocket.com/react-router-v6-guide/)
|
||||
- [How to use Routing in React JS: A Comprehensive Guide. ](https://teachingbee.in/how-to-use-routing-in-react-js/)
|
||||
- [React Router 6 – Tutorial for Beginners. ](https://www.youtube.com/watch?v=59IXY5IDrBA)
|
||||
|
||||
@@ -12,4 +12,4 @@ DDD connects the implementation to an evolving model and it is predicated on the
|
||||
|
||||
Visit the following resources to learn more:
|
||||
|
||||
- [Domain Driven Design Quickly](https://web.archive.org/web/20230606035225/https://matfrs2.github.io/RS2/predavanja/literatura/Avram%20A,%20Marinescu%20F.%20-%20Domain%20Driven%20Design%20Quickly.pdf)
|
||||
- [Domain Driven Design Quickly](https://matfrs2.github.io/RS2/predavanja/literatura/Avram%20A,%20Marinescu%20F.%20-%20Domain%20Driven%20Design%20Quickly.pdf)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import fp from '@fingerprintjs/fingerprintjs';
|
||||
import { TOKEN_COOKIE_NAME, removeAuthToken } from './jwt';
|
||||
import { TOKEN_COOKIE_NAME } from './jwt';
|
||||
|
||||
type HttpOptionsType = RequestInit | { headers: Record<string, any> };
|
||||
|
||||
@@ -30,10 +30,10 @@ type ApiReturn<ResponseType, ErrorType> = {
|
||||
*/
|
||||
export async function httpCall<
|
||||
ResponseType = AppResponse,
|
||||
ErrorType = AppError,
|
||||
ErrorType = AppError
|
||||
>(
|
||||
url: string,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
try {
|
||||
const fingerprintPromise = await fp.load({ monitoring: false });
|
||||
@@ -65,7 +65,7 @@ export async function httpCall<
|
||||
|
||||
// Logout user if token is invalid
|
||||
if (data.status === 401) {
|
||||
removeAuthToken();
|
||||
Cookies.remove(TOKEN_COOKIE_NAME);
|
||||
window.location.reload();
|
||||
return { response: undefined, error: data as ErrorType };
|
||||
}
|
||||
@@ -92,11 +92,11 @@ export async function httpCall<
|
||||
|
||||
export async function httpPost<
|
||||
ResponseType = AppResponse,
|
||||
ErrorType = AppError,
|
||||
ErrorType = AppError
|
||||
>(
|
||||
url: string,
|
||||
body: Record<string, any>,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
return httpCall<ResponseType, ErrorType>(url, {
|
||||
...options,
|
||||
@@ -108,7 +108,7 @@ export async function httpPost<
|
||||
export async function httpGet<ResponseType = AppResponse, ErrorType = AppError>(
|
||||
url: string,
|
||||
queryParams?: Record<string, any>,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
const searchParams = new URLSearchParams(queryParams).toString();
|
||||
const queryUrl = searchParams ? `${url}?${searchParams}` : url;
|
||||
@@ -122,11 +122,11 @@ export async function httpGet<ResponseType = AppResponse, ErrorType = AppError>(
|
||||
|
||||
export async function httpPatch<
|
||||
ResponseType = AppResponse,
|
||||
ErrorType = AppError,
|
||||
ErrorType = AppError
|
||||
>(
|
||||
url: string,
|
||||
body: Record<string, any>,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
return httpCall<ResponseType, ErrorType>(url, {
|
||||
...options,
|
||||
@@ -138,7 +138,7 @@ export async function httpPatch<
|
||||
export async function httpPut<ResponseType = AppResponse, ErrorType = AppError>(
|
||||
url: string,
|
||||
body: Record<string, any>,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
return httpCall<ResponseType, ErrorType>(url, {
|
||||
...options,
|
||||
@@ -149,10 +149,10 @@ export async function httpPut<ResponseType = AppResponse, ErrorType = AppError>(
|
||||
|
||||
export async function httpDelete<
|
||||
ResponseType = AppResponse,
|
||||
ErrorType = AppError,
|
||||
ErrorType = AppError
|
||||
>(
|
||||
url: string,
|
||||
options?: HttpOptionsType,
|
||||
options?: HttpOptionsType
|
||||
): Promise<ApiReturn<ResponseType, ErrorType>> {
|
||||
return httpCall<ResponseType, ErrorType>(url, {
|
||||
...options,
|
||||
|
||||
@@ -31,20 +31,3 @@ export function getUser() {
|
||||
|
||||
return decodeToken(token);
|
||||
}
|
||||
|
||||
export function setAuthToken(token: string) {
|
||||
Cookies.set(TOKEN_COOKIE_NAME, token, {
|
||||
path: '/',
|
||||
expires: 30,
|
||||
sameSite: 'lax',
|
||||
secure: true,
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
}
|
||||
|
||||
export function removeAuthToken() {
|
||||
Cookies.remove(TOKEN_COOKIE_NAME, {
|
||||
path: '/',
|
||||
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user