rxjs/operators#dematerialize TypeScript Examples
The following examples show how to use
rxjs/operators#dematerialize.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: fake-backend.service.ts From ng-conf-2020-workshop with MIT License | 6 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.users = JSON.parse(this.localStorage.getItem('users')) || [];
return of(null).pipe(mergeMap(() => {
// login user
if (request.url.endsWith('/login') && request.method === 'POST') {
return this.loginHandle(request);
}
// register user
if (request.url.endsWith('/register') && request.method === 'POST') {
const user = this.getStorageUser(request);
return this.registerHandle(user);
}
// login user with external provider
if (request.url.endsWith('/extlogin') && request.method === 'POST') {
const user = this.getStorageExtUser(request);
return this.registerHandle(user, true);
}
// Microsoft-specific OIDC discovery URI
if (request.url.endsWith('ms-discovery/keys') && request.method === 'GET') {
return of(new HttpResponse({ status: 200, body: msKeys }));
}
return next.handle(request);
}))
.pipe(materialize())
.pipe(dematerialize());
}
Example #2
Source File: fake-backend.ts From angular-10-basic-authentication-example with MIT License | 5 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users') && method === 'GET':
return getUsers();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName
})
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users);
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
}
function error(message) {
return throwError({ error: { message } });
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorised' } });
}
function isLoggedIn() {
return headers.get('Authorization') === `Basic ${window.btoa('test:test')}`;
}
}
Example #3
Source File: fake-backend.ts From angular-10-jwt-authentication-example with MIT License | 5 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users') && method === 'GET':
return getUsers();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
token: 'fake-jwt-token'
})
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users);
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
}
function error(message) {
return throwError({ error: { message } });
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorised' } });
}
function isLoggedIn() {
return headers.get('Authorization') === 'Bearer fake-jwt-token';
}
}
Example #4
Source File: fake-backend.ts From angular-9-jwt-authentication-example with MIT License | 5 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users') && method === 'GET':
return getUsers();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
token: 'fake-jwt-token'
})
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users);
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
}
function error(message) {
return throwError({ error: { message } });
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorised' } });
}
function isLoggedIn() {
return headers.get('Authorization') === 'Bearer fake-jwt-token';
}
}
Example #5
Source File: fake-backend.ts From angular-10-facebook-login-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/accounts/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/accounts') && method === 'GET':
return getAccounts();
case url.match(/\/accounts\/\d+$/) && method === 'GET':
return getAccountById();
case url.match(/\/accounts\/\d+$/) && method === 'PUT':
return updateAccount();
case url.match(/\/accounts\/\d+$/) && method === 'DELETE':
return deleteAccount();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { accessToken } = body;
return from(new Promise(resolve => {
fetch(`https://graph.facebook.com/v8.0/me?access_token=${accessToken}`)
.then(response => resolve(response.json()));
})).pipe(concatMap((data: any) => {
if (data.error) return unauthorized(data.error.message);
let account = accounts.find(x => x.facebookId === data.id);
if (!account) {
// create new account if first time logging in
account = {
id: newAccountId(),
facebookId: data.id,
name: data.name,
extraInfo: `This is some extra info about ${data.name} that is saved in the API`
}
accounts.push(account);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
}
return ok({
...account,
token: generateJwtToken(account)
});
}));
}
function getAccounts() {
if (!isLoggedIn()) return unauthorized();
return ok(accounts);
}
function getAccountById() {
if (!isLoggedIn()) return unauthorized();
let account = accounts.find(x => x.id === idFromUrl());
return ok(account);
}
function updateAccount() {
if (!isLoggedIn()) return unauthorized();
let params = body;
let account = accounts.find(x => x.id === idFromUrl());
// update and save account
Object.assign(account, params);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok(account);
}
function deleteAccount() {
if (!isLoggedIn()) return unauthorized();
// delete account then save
accounts = accounts.filter(x => x.id !== idFromUrl());
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500));
}
function unauthorized(message = 'Unauthorized') {
return throwError({ status: 401, error: { message } })
.pipe(materialize(), delay(500), dematerialize());
}
function isLoggedIn() {
return headers.get('Authorization')?.startsWith('Bearer fake-jwt-token');
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
function newAccountId() {
return accounts.length ? Math.max(...accounts.map(x => x.id)) + 1 : 1;
}
function generateJwtToken(account) {
// create token that expires in 15 minutes
const tokenPayload = {
exp: Math.round(new Date(Date.now() + 15*60*1000).getTime() / 1000),
id: account.id
}
return `fake-jwt-token.${btoa(JSON.stringify(tokenPayload))}`;
}
}
Example #6
Source File: fake-backend.ts From angular-10-jwt-refresh-tokens with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users/refresh-token') && method === 'POST':
return refreshToken();
case url.endsWith('/users/revoke-token') && method === 'POST':
return revokeToken();
case url.endsWith('/users') && method === 'GET':
return getUsers();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
// add refresh token to user
user.refreshTokens.push(generateRefreshToken());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
jwtToken: generateJwtToken()
})
}
function refreshToken() {
const refreshToken = getRefreshToken();
if (!refreshToken) return unauthorized();
const user = users.find(x => x.refreshTokens.includes(refreshToken));
if (!user) return unauthorized();
// replace old refresh token with a new one and save
user.refreshTokens = user.refreshTokens.filter(x => x !== refreshToken);
user.refreshTokens.push(generateRefreshToken());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
jwtToken: generateJwtToken()
})
}
function revokeToken() {
if (!isLoggedIn()) return unauthorized();
const refreshToken = getRefreshToken();
const user = users.find(x => x.refreshTokens.includes(refreshToken));
// revoke token and save
user.refreshTokens = user.refreshTokens.filter(x => x !== refreshToken);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users);
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
}
function error(message) {
return throwError({ error: { message } });
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorized' } });
}
function isLoggedIn() {
// check if jwt token is in auth header
const authHeader = headers.get('Authorization');
if (!authHeader.startsWith('Bearer fake-jwt-token')) return false;
// check if token is expired
const jwtToken = JSON.parse(atob(authHeader.split('.')[1]));
const tokenExpired = Date.now() > (jwtToken.exp * 1000);
if (tokenExpired) return false;
return true;
}
function generateJwtToken() {
// create token that expires in 15 minutes
const tokenPayload = { exp: Math.round(new Date(Date.now() + 15*60*1000).getTime() / 1000) }
return `fake-jwt-token.${btoa(JSON.stringify(tokenPayload))}`;
}
function generateRefreshToken() {
const token = new Date().getTime().toString();
// add token cookie that expires in 7 days
const expires = new Date(Date.now() + 7*24*60*60*1000).toUTCString();
document.cookie = `fakeRefreshToken=${token}; expires=${expires}; path=/`;
return token;
}
function getRefreshToken() {
// get refresh token from cookie
return (document.cookie.split(';').find(x => x.includes('fakeRefreshToken')) || '=').split('=')[1];
}
}
Example #7
Source File: fake-backend.ts From angular-10-registration-login-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users/register') && method === 'POST':
return register();
case url.endsWith('/users') && method === 'GET':
return getUsers();
case url.match(/\/users\/\d+$/) && method === 'GET':
return getUserById();
case url.match(/\/users\/\d+$/) && method === 'PUT':
return updateUser();
case url.match(/\/users\/\d+$/) && method === 'DELETE':
return deleteUser();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
...basicDetails(user),
token: 'fake-jwt-token'
})
}
function register() {
const user = body
if (users.find(x => x.username === user.username)) {
return error('Username "' + user.username + '" is already taken')
}
user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
users.push(user);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users.map(x => basicDetails(x)));
}
function getUserById() {
if (!isLoggedIn()) return unauthorized();
const user = users.find(x => x.id === idFromUrl());
return ok(basicDetails(user));
}
function updateUser() {
if (!isLoggedIn()) return unauthorized();
let params = body;
let user = users.find(x => x.id === idFromUrl());
// only update password if entered
if (!params.password) {
delete params.password;
}
// update and save user
Object.assign(user, params);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function deleteUser() {
if (!isLoggedIn()) return unauthorized();
users = users.filter(x => x.id !== idFromUrl());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500)); // delay observable to simulate server api call
}
function error(message) {
return throwError({ error: { message } })
.pipe(materialize(), delay(500), dematerialize()); // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648);
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorized' } })
.pipe(materialize(), delay(500), dematerialize());
}
function basicDetails(user) {
const { id, username, firstName, lastName } = user;
return { id, username, firstName, lastName };
}
function isLoggedIn() {
return headers.get('Authorization') === 'Bearer fake-jwt-token';
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
}
Example #8
Source File: fake-backend.ts From angular-10-role-based-authorization-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users') && method === 'GET':
return getUsers();
case url.match(/\/users\/\d+$/) && method === 'GET':
return getUserById();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
role: user.role,
token: `fake-jwt-token.${user.id}`
});
}
function getUsers() {
if (!isAdmin()) return unauthorized();
return ok(users);
}
function getUserById() {
if (!isLoggedIn()) return unauthorized();
// only admins can access other user records
if (!isAdmin() && currentUser().id !== idFromUrl()) return unauthorized();
const user = users.find(x => x.id === idFromUrl());
return ok(user);
}
// helper functions
function ok(body) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500)); // delay observable to simulate server api call
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'unauthorized' } })
.pipe(materialize(), delay(500), dematerialize()); // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648);
}
function error(message) {
return throwError({ status: 400, error: { message } })
.pipe(materialize(), delay(500), dematerialize());
}
function isLoggedIn() {
const authHeader = headers.get('Authorization') || '';
return authHeader.startsWith('Bearer fake-jwt-token');
}
function isAdmin() {
return isLoggedIn() && currentUser().role === Role.Admin;
}
function currentUser() {
if (!isLoggedIn()) return;
const id = parseInt(headers.get('Authorization').split('.')[1]);
return users.find(x => x.id === id);
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
}
Example #9
Source File: fake-backend.ts From angular-10-signup-verification-boilerplate with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
const alertService = this.alertService;
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/accounts/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/accounts/refresh-token') && method === 'POST':
return refreshToken();
case url.endsWith('/accounts/revoke-token') && method === 'POST':
return revokeToken();
case url.endsWith('/accounts/register') && method === 'POST':
return register();
case url.endsWith('/accounts/verify-email') && method === 'POST':
return verifyEmail();
case url.endsWith('/accounts/forgot-password') && method === 'POST':
return forgotPassword();
case url.endsWith('/accounts/validate-reset-token') && method === 'POST':
return validateResetToken();
case url.endsWith('/accounts/reset-password') && method === 'POST':
return resetPassword();
case url.endsWith('/accounts') && method === 'GET':
return getAccounts();
case url.match(/\/accounts\/\d+$/) && method === 'GET':
return getAccountById();
case url.endsWith('/accounts') && method === 'POST':
return createAccount();
case url.match(/\/accounts\/\d+$/) && method === 'PUT':
return updateAccount();
case url.match(/\/accounts\/\d+$/) && method === 'DELETE':
return deleteAccount();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { email, password } = body;
const account = accounts.find(x => x.email === email && x.password === password && x.isVerified);
if (!account) return error('Email or password is incorrect');
// add refresh token to account
account.refreshTokens.push(generateRefreshToken());
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok({
...basicDetails(account),
jwtToken: generateJwtToken(account)
});
}
function refreshToken() {
const refreshToken = getRefreshToken();
if (!refreshToken) return unauthorized();
const account = accounts.find(x => x.refreshTokens.includes(refreshToken));
if (!account) return unauthorized();
// replace old refresh token with a new one and save
account.refreshTokens = account.refreshTokens.filter(x => x !== refreshToken);
account.refreshTokens.push(generateRefreshToken());
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok({
...basicDetails(account),
jwtToken: generateJwtToken(account)
});
}
function revokeToken() {
if (!isAuthenticated()) return unauthorized();
const refreshToken = getRefreshToken();
const account = accounts.find(x => x.refreshTokens.includes(refreshToken));
// revoke token and save
account.refreshTokens = account.refreshTokens.filter(x => x !== refreshToken);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
function register() {
const account = body;
if (accounts.find(x => x.email === account.email)) {
// display email already registered "email" in alert
setTimeout(() => {
alertService.info(`
<h4>Email Already Registered</h4>
<p>Your email ${account.email} is already registered.</p>
<p>If you don't know your password please visit the <a href="${location.origin}/account/forgot-password">forgot password</a> page.</p>
<div><strong>NOTE:</strong> The fake backend displayed this "email" so you can test without an api. A real backend would send a real email.</div>
`, { autoClose: false });
}, 1000);
// always return ok() response to prevent email enumeration
return ok();
}
// assign account id and a few other properties then save
account.id = newAccountId();
if (account.id === 1) {
// first registered account is an admin
account.role = Role.Admin;
} else {
account.role = Role.User;
}
account.dateCreated = new Date().toISOString();
account.verificationToken = new Date().getTime().toString();
account.isVerified = false;
account.refreshTokens = [];
delete account.confirmPassword;
accounts.push(account);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
// display verification email in alert
setTimeout(() => {
const verifyUrl = `${location.origin}/account/verify-email?token=${account.verificationToken}`;
alertService.info(`
<h4>Verification Email</h4>
<p>Thanks for registering!</p>
<p>Please click the below link to verify your email address:</p>
<p><a href="${verifyUrl}">${verifyUrl}</a></p>
<div><strong>NOTE:</strong> The fake backend displayed this "email" so you can test without an api. A real backend would send a real email.</div>
`, { autoClose: false });
}, 1000);
return ok();
}
function verifyEmail() {
const { token } = body;
const account = accounts.find(x => !!x.verificationToken && x.verificationToken === token);
if (!account) return error('Verification failed');
// set is verified flag to true if token is valid
account.isVerified = true;
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
function forgotPassword() {
const { email } = body;
const account = accounts.find(x => x.email === email);
// always return ok() response to prevent email enumeration
if (!account) return ok();
// create reset token that expires after 24 hours
account.resetToken = new Date().getTime().toString();
account.resetTokenExpires = new Date(Date.now() + 24*60*60*1000).toISOString();
localStorage.setItem(accountsKey, JSON.stringify(accounts));
// display password reset email in alert
setTimeout(() => {
const resetUrl = `${location.origin}/account/reset-password?token=${account.resetToken}`;
alertService.info(`
<h4>Reset Password Email</h4>
<p>Please click the below link to reset your password, the link will be valid for 1 day:</p>
<p><a href="${resetUrl}">${resetUrl}</a></p>
<div><strong>NOTE:</strong> The fake backend displayed this "email" so you can test without an api. A real backend would send a real email.</div>
`, { autoClose: false });
}, 1000);
return ok();
}
function validateResetToken() {
const { token } = body;
const account = accounts.find(x =>
!!x.resetToken && x.resetToken === token &&
new Date() < new Date(x.resetTokenExpires)
);
if (!account) return error('Invalid token');
return ok();
}
function resetPassword() {
const { token, password } = body;
const account = accounts.find(x =>
!!x.resetToken && x.resetToken === token &&
new Date() < new Date(x.resetTokenExpires)
);
if (!account) return error('Invalid token');
// update password and remove reset token
account.password = password;
account.isVerified = true;
delete account.resetToken;
delete account.resetTokenExpires;
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
function getAccounts() {
if (!isAuthenticated()) return unauthorized();
return ok(accounts.map(x => basicDetails(x)));
}
function getAccountById() {
if (!isAuthenticated()) return unauthorized();
let account = accounts.find(x => x.id === idFromUrl());
// user accounts can get own profile and admin accounts can get all profiles
if (account.id !== currentAccount().id && !isAuthorized(Role.Admin)) {
return unauthorized();
}
return ok(basicDetails(account));
}
function createAccount() {
if (!isAuthorized(Role.Admin)) return unauthorized();
const account = body;
if (accounts.find(x => x.email === account.email)) {
return error(`Email ${account.email} is already registered`);
}
// assign account id and a few other properties then save
account.id = newAccountId();
account.dateCreated = new Date().toISOString();
account.isVerified = true;
account.refreshTokens = [];
delete account.confirmPassword;
accounts.push(account);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
function updateAccount() {
if (!isAuthenticated()) return unauthorized();
let params = body;
let account = accounts.find(x => x.id === idFromUrl());
// user accounts can update own profile and admin accounts can update all profiles
if (account.id !== currentAccount().id && !isAuthorized(Role.Admin)) {
return unauthorized();
}
// only update password if included
if (!params.password) {
delete params.password;
}
// don't save confirm password
delete params.confirmPassword;
// update and save account
Object.assign(account, params);
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok(basicDetails(account));
}
function deleteAccount() {
if (!isAuthenticated()) return unauthorized();
let account = accounts.find(x => x.id === idFromUrl());
// user accounts can delete own account and admin accounts can delete any account
if (account.id !== currentAccount().id && !isAuthorized(Role.Admin)) {
return unauthorized();
}
// delete account then save
accounts = accounts.filter(x => x.id !== idFromUrl());
localStorage.setItem(accountsKey, JSON.stringify(accounts));
return ok();
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500)); // delay observable to simulate server api call
}
function error(message) {
return throwError({ error: { message } })
.pipe(materialize(), delay(500), dematerialize()); // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648);
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorized' } })
.pipe(materialize(), delay(500), dematerialize());
}
function basicDetails(account) {
const { id, title, firstName, lastName, email, role, dateCreated, isVerified } = account;
return { id, title, firstName, lastName, email, role, dateCreated, isVerified };
}
function isAuthenticated() {
return !!currentAccount();
}
function isAuthorized(role) {
const account = currentAccount();
if (!account) return false;
return account.role === role;
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
function newAccountId() {
return accounts.length ? Math.max(...accounts.map(x => x.id)) + 1 : 1;
}
function currentAccount() {
// check if jwt token is in auth header
const authHeader = headers.get('Authorization');
if (!authHeader.startsWith('Bearer fake-jwt-token')) return;
// check if token is expired
const jwtToken = JSON.parse(atob(authHeader.split('.')[1]));
const tokenExpired = Date.now() > (jwtToken.exp * 1000);
if (tokenExpired) return;
const account = accounts.find(x => x.id === jwtToken.id);
return account;
}
function generateJwtToken(account) {
// create token that expires in 15 minutes
const tokenPayload = {
exp: Math.round(new Date(Date.now() + 15*60*1000).getTime() / 1000),
id: account.id
}
return `fake-jwt-token.${btoa(JSON.stringify(tokenPayload))}`;
}
function generateRefreshToken() {
const token = new Date().getTime().toString();
// add token cookie that expires in 7 days
const expires = new Date(Date.now() + 7*24*60*60*1000).toUTCString();
document.cookie = `fakeRefreshToken=${token}; expires=${expires}; path=/`;
return token;
}
function getRefreshToken() {
// get refresh token from cookie
return (document.cookie.split(';').find(x => x.includes('fakeRefreshToken')) || '=').split('=')[1];
}
}
Example #10
Source File: fake-backend.ts From angular-11-crud-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/users') && method === 'GET':
return getUsers();
case url.match(/\/users\/\d+$/) && method === 'GET':
return getUserById();
case url.endsWith('/users') && method === 'POST':
return createUser();
case url.match(/\/users\/\d+$/) && method === 'PUT':
return updateUser();
case url.match(/\/users\/\d+$/) && method === 'DELETE':
return deleteUser();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function getUsers() {
return ok(users.map(x => basicDetails(x)));
}
function getUserById() {
const user = users.find(x => x.id === idFromUrl());
return ok(basicDetails(user));
}
function createUser() {
const user = body;
if (users.find(x => x.email === user.email)) {
return error(`User with the email ${user.email} already exists`);
}
// assign user id and a few other properties then save
user.id = newUserId();
delete user.confirmPassword;
users.push(user);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function updateUser() {
let params = body;
let user = users.find(x => x.id === idFromUrl());
if (params.email !== user.email && users.find(x => x.email === params.email)) {
return error(`User with the email ${params.email} already exists`);
}
// only update password if entered
if (!params.password) {
delete params.password;
}
// update and save user
Object.assign(user, params);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function deleteUser() {
users = users.filter(x => x.id !== idFromUrl());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
// helper functions
function ok(body?: any) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500)); // delay observable to simulate server api call
}
function error(message: any) {
return throwError({ error: { message } })
.pipe(materialize(), delay(500), dematerialize()); // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648);
}
function basicDetails(user: any) {
const { id, title, firstName, lastName, email, role } = user;
return { id, title, firstName, lastName, email, role };
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
function newUserId() {
return users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
}
}
Example #11
Source File: fake-backend.ts From angular-9-jwt-refresh-tokens with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users/refresh-token') && method === 'POST':
return refreshToken();
case url.endsWith('/users/revoke-token') && method === 'POST':
return revokeToken();
case url.endsWith('/users') && method === 'GET':
return getUsers();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
// add refresh token to user
user.refreshTokens.push(generateRefreshToken());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
jwtToken: generateJwtToken()
})
}
function refreshToken() {
const refreshToken = getRefreshToken();
if (!refreshToken) return unauthorized();
const user = users.find(x => x.refreshTokens.includes(refreshToken));
if (!user) return unauthorized();
// replace old refresh token with a new one and save
user.refreshTokens = user.refreshTokens.filter(x => x !== refreshToken);
user.refreshTokens.push(generateRefreshToken());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
jwtToken: generateJwtToken()
})
}
function revokeToken() {
if (!isLoggedIn()) return unauthorized();
const refreshToken = getRefreshToken();
const user = users.find(x => x.refreshTokens.includes(refreshToken));
// revoke token and save
user.refreshTokens = user.refreshTokens.filter(x => x !== refreshToken);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function getUsers() {
if (!isLoggedIn()) return unauthorized();
return ok(users);
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
}
function error(message) {
return throwError({ error: { message } });
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'Unauthorized' } });
}
function isLoggedIn() {
// check if jwt token is in auth header
const authHeader = headers.get('Authorization');
if (!authHeader.startsWith('Bearer fake-jwt-token')) return false;
// check if token is expired
const jwtToken = JSON.parse(atob(authHeader.split('.')[1]));
const tokenExpired = Date.now() > (jwtToken.exp * 1000);
if (tokenExpired) return false;
return true;
}
function generateJwtToken() {
// create token that expires in 15 minutes
const tokenPayload = { exp: Math.round(new Date(Date.now() + 15*60*1000).getTime() / 1000) }
return `fake-jwt-token.${btoa(JSON.stringify(tokenPayload))}`;
}
function generateRefreshToken() {
const token = new Date().getTime().toString();
// add token cookie that expires in 7 days
const expires = new Date(Date.now() + 7*24*60*60*1000).toUTCString();
document.cookie = `fakeRefreshToken=${token}; expires=${expires}; path=/`;
return token;
}
function getRefreshToken() {
// get refresh token from cookie
return (document.cookie.split(';').find(x => x.includes('fakeRefreshToken')) || '=').split('=')[1];
}
}
Example #12
Source File: fake-backend.ts From angular-9-role-based-authorization-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
.pipe(delay(500))
.pipe(dematerialize());
function handleRoute() {
switch (true) {
case url.endsWith('/users/authenticate') && method === 'POST':
return authenticate();
case url.endsWith('/users') && method === 'GET':
return getUsers();
case url.match(/\/users\/\d+$/) && method === 'GET':
return getUserById();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function authenticate() {
const { username, password } = body;
const user = users.find(x => x.username === username && x.password === password);
if (!user) return error('Username or password is incorrect');
return ok({
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
role: user.role,
token: `fake-jwt-token.${user.id}`
});
}
function getUsers() {
if (!isAdmin()) return unauthorized();
return ok(users);
}
function getUserById() {
if (!isLoggedIn()) return unauthorized();
// only admins can access other user records
if (!isAdmin() && currentUser().id !== idFromUrl()) return unauthorized();
const user = users.find(x => x.id === idFromUrl());
return ok(user);
}
// helper functions
function ok(body) {
return of(new HttpResponse({ status: 200, body }));
}
function unauthorized() {
return throwError({ status: 401, error: { message: 'unauthorized' } });
}
function error(message) {
return throwError({ status: 400, error: { message } });
}
function isLoggedIn() {
const authHeader = headers.get('Authorization') || '';
return authHeader.startsWith('Bearer fake-jwt-token');
}
function isAdmin() {
return isLoggedIn() && currentUser().role === Role.Admin;
}
function currentUser() {
if (!isLoggedIn()) return;
const id = parseInt(headers.get('Authorization').split('.')[1]);
return users.find(x => x.id === id);
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
}
Example #13
Source File: fake-backend.ts From angular-master-details-crud-example with MIT License | 4 votes |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const { url, method, headers, body } = request;
return handleRoute();
function handleRoute() {
switch (true) {
case url.endsWith('/users') && method === 'GET':
return getUsers();
case url.match(/\/users\/\d+$/) && method === 'GET':
return getUserById();
case url.endsWith('/users') && method === 'POST':
return createUser();
case url.match(/\/users\/\d+$/) && method === 'PUT':
return updateUser();
case url.match(/\/users\/\d+$/) && method === 'DELETE':
return deleteUser();
default:
// pass through any requests not handled above
return next.handle(request);
}
}
// route functions
function getUsers() {
return ok(users.map(x => basicDetails(x)));
}
function getUserById() {
const user = users.find(x => x.id === idFromUrl());
return ok(basicDetails(user));
}
function createUser() {
const user = body;
if (users.find(x => x.email === user.email)) {
return error(`User with the email ${user.email} already exists`);
}
// assign user id and a few other properties then save
user.id = newUserId();
delete user.confirmPassword;
users.push(user);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function updateUser() {
let params = body;
let user = users.find(x => x.id === idFromUrl());
// only update password if entered
if (!params.password) {
delete params.password;
}
// update and save user
Object.assign(user, params);
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
function deleteUser() {
users = users.filter(x => x.id !== idFromUrl());
localStorage.setItem(usersKey, JSON.stringify(users));
return ok();
}
// helper functions
function ok(body?) {
return of(new HttpResponse({ status: 200, body }))
.pipe(delay(500)); // delay observable to simulate server api call
}
function error(message) {
return throwError({ error: { message } })
.pipe(materialize(), delay(500), dematerialize()); // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648);
}
function basicDetails(user) {
const { id, title, firstName, lastName, email, role } = user;
return { id, title, firstName, lastName, email, role };
}
function idFromUrl() {
const urlParts = url.split('/');
return parseInt(urlParts[urlParts.length - 1]);
}
function newUserId() {
return users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
}
}
Example #14
Source File: fake-backend-interceptor.ts From np-ui-lib with MIT License | 4 votes |
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<any> {
const { url, method, body } = request;
if (
url.endsWith("/getAllUsers") ||
url.endsWith("/getAllUsers") ||
url.endsWith("/updateUsers")
) {
// wrap in delayed observable to simulate server api call
return of(null)
.pipe(mergeMap(handleRoute))
.pipe(materialize())
.pipe(delay(1000))
.pipe(dematerialize());
}
return next.handle(request);
function handleRoute(): any {
switch (true) {
case url.endsWith("/getAllUsers") && method === "GET":
return getAllUsers();
case url.endsWith("/getAllUsers") && method === "POST":
return getAllUsersWithOptions(body);
case url.endsWith("/updateUsers") && method === "POST":
return updateUsers(body);
}
}
function getAllUsers() {
return ok(data);
}
function getAllUsersWithOptions(loadOptions: any) {
let data2 = data;
if (loadOptions.filterColumns && loadOptions.filterColumns.length > 0) {
data2 = filterData(data2, loadOptions.filterColumns);
}
if (loadOptions.sortColumns && loadOptions.sortColumns.length > 0) {
for (const element of loadOptions.sortColumns) {
data2 = _.orderBy(data2, element.dataField, element.sortDirection);
}
}
const startIndex = (loadOptions.pageNumber - 1) * loadOptions.pageSize;
const endIndex = Math.min(
startIndex + loadOptions.pageSize - 1,
data2.length - 1
);
const result = {
data: data2.slice(startIndex, endIndex + 1),
total: data2.length,
};
return ok(result);
}
function filterData(dataSource: any, filterColumns: any[]) {
for (const element of filterColumns) {
if (element.filterOperator === "startswith") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return _.startsWith(
a[element.dataField].toLowerCase(),
element.filterValue.toLowerCase()
);
});
} else if (element.filterOperator === "endswith") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return _.endsWith(
a[element.dataField].toLowerCase(),
element.filterValue.toLowerCase()
);
});
} else if (element.filterOperator === "contains") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField]
.toLowerCase()
.indexOf(element.filterValue.toLowerCase()) !== -1
);
});
} else if (element.filterOperator === "gt") {
if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] > Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) >
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
}
} else if (element.filterOperator === "ge") {
if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] >= Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) >=
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
}
} else if (element.filterOperator === "lt") {
if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] < Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) <
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
}
} else if (element.filterOperator === "le") {
if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] <= Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) <=
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
}
} else if (element.filterOperator === "eq") {
if (element.dataType === "boolean") {
if (element.filterValue === "true") {
dataSource = _.filter(dataSource, (a) => {
return a[element.dataField] === true;
});
} else {
dataSource = _.filter(dataSource, (a) => {
return a[element.dataField] === false;
});
}
} else if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] === Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) ===
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
} else if (element.dataType === "string") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].toLowerCase() ===
element.filterValue.toLowerCase()
);
});
}
} else if (element.filterOperator === "ne") {
if (element.dataType === "boolean") {
if (element.filterValue === "true") {
dataSource = _.filter(dataSource, (a) => {
return a[element.dataField] !== true;
});
} else {
dataSource = _.filter(dataSource, (a) => {
return a[element.dataField] !== false;
});
}
} else if (element.dataType === "number") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return a[element.dataField] !== Number(element.filterValue);
});
} else if (element.dataType === "date") {
dataSource = _.filter(dataSource, (a) => {
if (!a[element.dataField]) {
return false;
}
return (
a[element.dataField].setHours(0, 0, 0, 0) !==
new Date(element.filterValue).setHours(0, 0, 0, 0)
);
});
}
}
}
return dataSource;
}
function ok(response: any) {
return of(
new HttpResponse({
status: 200,
body: JSON.parse(JSON.stringify(response)),
})
);
}
function updateUsers(keys: any[]) {
const records = data.filter((element) => {
if (keys.indexOf(element.Id) > -1) {
return element;
}
});
if (records) {
records.forEach((element: any) => {
element.FirstName = element.FirstName + " updated";
});
}
return ok(true);
}
}