Skip to content

Commit a76542f

Browse files
authored
Merge pull request #1 from AXeL-dev/enforce-user-security
Enforce user security
2 parents 5de21c2 + aacda7a commit a76542f

18 files changed

Lines changed: 96 additions & 39 deletions

README.md

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,72 @@ npm install --save ng-fire-admin
156156

157157
**7**. In order to protect your database & storage data, you must set the following rules in your firebase console:
158158

159+
<details>
160+
<summary>How to setup your firebase project?</summary>
161+
162+
- Start by adding a new project in your firebase console.
163+
164+
- Enable Authentication by email & password.
165+
166+
- Add a database to your project.
167+
168+
- Add a storage.
169+
</details>
170+
159171
**Firestore Database rules:**
160172

161173
```javascript
162174
rules_version = '2';
163175
service cloud.firestore {
164176
match /databases/{database}/documents {
165-
match /{collection}/{document=**} {
166-
allow read: if collection != 'users' || request.auth != null;
167-
allow write: if request.auth != null;
177+
match /{collection}/{document}/{path=**} {
178+
allow read: if isPublic(collection, document) || isAdmin();
179+
allow write: if registrationEnabled(collection) || isAdmin() || (isEditor() && isPublic(collection, document));
180+
}
181+
function isPublic(collection, document) {
182+
return collection != 'config' && (collection != 'users' || isOwner(document));
183+
}
184+
function isSignedIn() {
185+
return request.auth != null;
186+
}
187+
function hasRole(role) {
188+
return isSignedIn() && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == role;
189+
}
190+
function isAdmin() {
191+
return hasRole('admin');
192+
}
193+
function isEditor() {
194+
return hasRole('editor');
195+
}
196+
function isOwner(ownerId) {
197+
return isSignedIn() && request.auth.uid == ownerId;
198+
}
199+
function registrationEnabled(collection) {
200+
return collection == 'users' && (
201+
!exists(/databases/$(database)/documents/config/registration) ||
202+
get(/databases/$(database)/documents/config/registration).data.enabled
203+
);
168204
}
169205
}
170206
}
171207
```
172208

209+
<details>
210+
<summary>More basic database rules? (not recommended)</summary>
211+
212+
```javascript
213+
rules_version = '2';
214+
service cloud.firestore {
215+
match /databases/{database}/documents {
216+
match /{collection}/{document=**} {
217+
allow read: if collection != 'users' || request.auth != null;
218+
allow write: if request.auth != null;
219+
}
220+
}
221+
}
222+
```
223+
</details>
224+
173225
**Storage rules:**
174226

175227
```javascript

projects/fire-admin/src/lib/components/dashboard/dashboard.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ <h6 class="stats-small__value count my-3">{{ statistics?.comments || 0 }}</h6>
4444
</div>
4545
</div>
4646
</div>
47-
<div class="col-lg col-md-4 col-sm-6 mb-4">
47+
<div class="col-lg col-md-4 col-sm-6 mb-4" *ngIf="currentUser?.isAdmin()">
4848
<div class="stats-small stats-small--1 card card-small">
4949
<div class="card-body p-0 d-flex">
5050
<div class="d-flex flex-column m-auto">
@@ -56,7 +56,7 @@ <h6 class="stats-small__value count my-3">{{ statistics?.users || 0 }}</h6>
5656
</div>
5757
</div>
5858
</div>
59-
<div class="col-lg col-md-4 col-sm-12 mb-4">
59+
<div class="col-lg col-md-4 mb-4" [ngClass]="currentUser?.isAdmin() ? 'col-sm-12' : 'col-sm-6'">
6060
<div class="stats-small stats-small--1 card card-small">
6161
<div class="card-body p-0 d-flex">
6262
<div class="d-flex flex-column m-auto">

projects/fire-admin/src/lib/components/dashboard/dashboard.component.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { map, takeUntil } from 'rxjs/operators';
1313
import { NavigationService } from '../../services/navigation.service';
1414
import { initPieChart } from '../../helpers/charts.helper';
1515
import { I18nService } from '../../services/i18n.service';
16+
import { CurrentUserService } from '../../services/current-user.service';
1617

1718
type PostByStatus = {
1819
label: string,
@@ -47,6 +48,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
4748
private categories: CategoriesService,
4849
private settings: SettingsService,
4950
public navigation: NavigationService,
51+
public currentUser: CurrentUserService,
5052
private i18n: I18nService
5153
) { }
5254

@@ -88,7 +90,9 @@ export class DashboardComponent implements OnInit, OnDestroy {
8890
this.statistics.posts = await this.posts.countAll();
8991
this.statistics.pages = await this.pages.countAll();
9092
this.statistics.comments = 0; // ToDo
91-
this.statistics.users = await this.users.countAll();
93+
if (this.currentUser.isAdmin()) {
94+
this.statistics.users = await this.users.countAll();
95+
}
9296
this.statistics.translations = await this.translations.countAll();
9397
}
9498

projects/fire-admin/src/lib/components/pages/list/pages-list.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ <h3 class="page-title">{{ 'List' | translate }}</h3>
2020
<th>{{ 'PageLanguage' | translate }}</th>
2121
<th>{{ 'PageCreatedAt' | translate }}</th>
2222
<th>{{ 'PageUpdatedAt' | translate }}</th>
23-
<th>{{ 'PageAuthor' | translate }}</th>
23+
<th *ngIf="currentUser?.isAdmin()">{{ 'PageAuthor' | translate }}</th>
2424
<th class="text-right hide-sort-icons">{{ 'Actions' | translate }}</th>
2525
</tr>
2626
</thead>
@@ -38,7 +38,7 @@ <h3 class="page-title">{{ 'List' | translate }}</h3>
3838
<td>{{ allLanguages[page.lang].label | translate }}</td>
3939
<td>{{ page.createdAt | datetime }}</td>
4040
<td>{{ page.updatedAt | datetime }}</td>
41-
<td>
41+
<td *ngIf="currentUser?.isAdmin()">
4242
<a *ngIf="page.createdBy" [routerLink]="navigation.getRouterLink('users', 'profile', page.createdBy)">
4343
{{ page.author | async }}
4444
</a>

projects/fire-admin/src/lib/components/pages/list/pages-list.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
22
import { DataTableDirective } from 'angular-datatables';
33
import { Subject, Subscription, Observable } from 'rxjs';
44
import { map, takeUntil } from 'rxjs/operators';
5-
import { refreshDataTable, clearDataTable } from '../../../helpers/datatables.helper';
5+
import { refreshDataTable } from '../../../helpers/datatables.helper';
66
import { AlertService } from '../../../services/alert.service';
77
import { NavigationService } from '../../../services/navigation.service';
88
import { I18nService } from '../../../services/i18n.service';
@@ -11,6 +11,7 @@ import { SettingsService } from '../../../services/settings.service';
1111
import { Language } from '../../../models/language.model';
1212
import { PagesService } from '../../../services/collections/pages.service';
1313
import { Page } from '../../../models/collections/page.model';
14+
import { CurrentUserService } from '../../../services/current-user.service';
1415

1516
@Component({
1617
selector: 'fa-pages-list',
@@ -38,6 +39,7 @@ export class PagesListComponent implements OnInit, OnDestroy {
3839
private i18n: I18nService,
3940
private route: ActivatedRoute,
4041
public navigation: NavigationService,
42+
public currentUser: CurrentUserService,
4143
private settings: SettingsService
4244
) { }
4345

@@ -90,8 +92,6 @@ export class PagesListComponent implements OnInit, OnDestroy {
9092
translationId: page.translationId,
9193
translations: page.translations
9294
}).then(() => {
93-
clearDataTable(this.dataTableElement);
94-
this.isLoading = true;
9595
this.alert.success(this.i18n.get('PageDeleted', { title: page.title }), false, 5000);
9696
}).catch((error: Error) => {
9797
this.alert.error(error.message);

projects/fire-admin/src/lib/components/posts/categories/posts-categories.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class PostsCategoriesComponent implements OnInit, OnDestroy {
5656
this.allCategories.subscribe((categories: Category[]) => {
5757
// console.log(categories);
5858
// Refresh datatable on data change
59-
refreshDataTable(this.dataTableElement, this.dataTableTrigger);
59+
refreshDataTable(this.dataTableElement, this.dataTableTrigger, true);
6060
})
6161
);
6262
}

projects/fire-admin/src/lib/components/posts/list/posts-list.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ <h3 class="page-title">{{ 'List' | translate }}</h3>
2323
<th>{{ 'Categories' | translate }}</th>
2424
<th>{{ 'PostCreatedAt' | translate }}</th>
2525
<th>{{ 'PostUpdatedAt' | translate }}</th>
26-
<th>{{ 'PostAuthor' | translate }}</th>
26+
<th *ngIf="currentUser?.isAdmin()">{{ 'PostAuthor' | translate }}</th>
2727
<th class="text-right hide-sort-icons">{{ 'Actions' | translate }}</th>
2828
</tr>
2929
</thead>
@@ -51,7 +51,7 @@ <h3 class="page-title">{{ 'List' | translate }}</h3>
5151
</td>
5252
<td>{{ post.createdAt | datetime }}</td>
5353
<td>{{ post.updatedAt | datetime }}</td>
54-
<td>
54+
<td *ngIf="currentUser?.isAdmin()">
5555
<a *ngIf="post.createdBy" [routerLink]="navigation.getRouterLink('users', 'profile', post.createdBy)">
5656
{{ post.author | async }}
5757
</a>

projects/fire-admin/src/lib/components/posts/list/posts-list.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Subject, Subscription, Observable } from 'rxjs';
44
import { Post, PostStatus } from '../../../models/collections/post.model';
55
import { PostsService } from '../../../services/collections/posts.service';
66
import { map, takeUntil } from 'rxjs/operators';
7-
import { refreshDataTable, clearDataTable } from '../../../helpers/datatables.helper';
7+
import { refreshDataTable } from '../../../helpers/datatables.helper';
88
import { AlertService } from '../../../services/alert.service';
99
import { NavigationService } from '../../../services/navigation.service';
1010
import { I18nService } from '../../../services/i18n.service';
@@ -13,6 +13,7 @@ import { CategoriesService } from '../../../services/collections/categories.serv
1313
import { ActivatedRoute } from '@angular/router';
1414
import { SettingsService } from '../../../services/settings.service';
1515
import { Language } from '../../../models/language.model';
16+
import { CurrentUserService } from '../../../services/current-user.service';
1617

1718
@Component({
1819
selector: 'fa-posts-list',
@@ -43,6 +44,7 @@ export class PostsListComponent implements OnInit, OnDestroy {
4344
private i18n: I18nService,
4445
private route: ActivatedRoute,
4546
public navigation: NavigationService,
47+
public currentUser: CurrentUserService,
4648
private settings: SettingsService
4749
) { }
4850

@@ -136,8 +138,6 @@ export class PostsListComponent implements OnInit, OnDestroy {
136138
translationId: post.translationId,
137139
translations: post.translations
138140
}).then(() => {
139-
clearDataTable(this.dataTableElement);
140-
this.isLoading = true;
141141
this.alert.success(this.i18n.get('PostDeleted', { title: post.title }), false, 5000);
142142
}).catch((error: Error) => {
143143
this.alert.error(error.message);

projects/fire-admin/src/lib/components/translations/translations.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class TranslationsComponent implements OnInit, OnDestroy, AfterViewInit {
5353
this.allTranslations.subscribe((translations: TranslationData[]) => {
5454
// console.log(translations);
5555
// Refresh datatable on data change
56-
refreshDataTable(this.dataTableElement, this.dataTableTrigger);
56+
refreshDataTable(this.dataTableElement, this.dataTableTrigger, true);
5757
})
5858
);
5959
}

projects/fire-admin/src/lib/components/users/list/users-list.component.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ <h3 class="page-title">{{ 'List' | translate }}</h3>
4444
<td>{{ user.updatedAt | datetime }}</td>
4545
<td>
4646
<a *ngIf="user.createdBy" [routerLink]="navigation.getRouterLink('users', 'profile', user.createdBy)">
47-
<span *ngIf="user.creator | async as creator">
48-
{{ creator.firstName + ' ' + creator.lastName }}
49-
</span>
47+
<span *ngIf="user.creator | async as creator">{{ creator }}</span>
5048
</a>
5149
</td>
5250
<td class="text-right">

0 commit comments

Comments
 (0)