Skip to content

Commit

Permalink
Merge pull request #151 from AurelicButter/feature/966
Browse files Browse the repository at this point in the history
[Feature/966] Account Permissions Redesign
  • Loading branch information
AurelicButter authored Nov 14, 2024
2 parents 4ee039f + 947e5a1 commit 70efbca
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 150 deletions.
13 changes: 8 additions & 5 deletions src/app/admin-pages/home-panel/home-panel.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { Component } from "@angular/core";
import { LocalCookiesService } from "src/app/services/authentication/local-cookies.service";
import { AuthUser } from "src/app/models/AuthUser";
import { AuthUserService } from "src/app/services/authentication/auth-user.service";

@Component({
selector: "home-panel",
templateUrl: "./home-panel.component.html",
styleUrls: ["./home-panel.component.css"]
})
export class HomePanelComponent {
user: any;
user: AuthUser;

constructor(private cookieService: LocalCookiesService) {
this.cookieService.userEvent.subscribe((value) => {
this.user = value;
constructor(private AuthUser: AuthUserService) {
this.AuthUser.userEvent.subscribe((value) => {
if (value !== null) {
this.user = value;
}
});
}
}
2 changes: 1 addition & 1 deletion src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { MissingPageComponent } from "./pages/missing-page/missing-page.componen
import { SeriesPageComponent } from "./pages/series-page/series-page.component";
import { SearchPageComponent } from "./search-page/search-page.component";
import { LoginPageComponent } from "./pages/login/login.component";
import { AuthenticationGuard } from "./services/authentication/authentication.guard";
import { AuthenticationGuard } from "./guards/authentication.guard";
import { UserSettingsPageComponent } from "./user-settings-page/user-settings-page.component";
import { RegistrationPageComponent } from "./pages/registration/registration.component";

Expand Down
10 changes: 5 additions & 5 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, OnInit } from "@angular/core";
import { LocalCookiesService } from "./services/authentication/local-cookies.service";
import { AuthenticationService } from "./services/authentication/authentication.service";
import { AuthUserService } from "./services/authentication/auth-user.service";

@Component({
selector: "app-root",
Expand All @@ -14,16 +14,16 @@ export class AppComponent implements OnInit {

constructor(
private authService: AuthenticationService,
private cookieService: LocalCookiesService
private AuthUser: AuthUserService
) {
this.cookieService.userEvent.subscribe((value) => {
this.isAuthenticated = Object.keys(value).length > 0;
this.AuthUser.userEvent.subscribe(() => {
this.isAuthenticated = this.AuthUser.isLoggedIn();
});
}

ngOnInit(): void {
if (this.isAuthenticated) {
this.authService.isLoggedIn().subscribe((value) => {
this.authService.validateCookies().subscribe((value) => {
this.isAuthenticated = value ? true : false;
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import { MatDialogModule } from "@angular/material/dialog";
import { SearchPageModule } from "./search-page/search-page.module";
import { LoginPageComponent } from "./pages/login/login.component";
import { UserNavMenuComponent } from "./user-nav-menu/user-nav-menu.component";
import { LocalCookiesService } from "./services/authentication/local-cookies.service";
import { UserSettingsPageComponent } from "./user-settings-page/user-settings-page.component";
import { RegistrationPageComponent } from "./pages/registration/registration.component";
import { SharedModule } from "./shared/shared.module";
import { DeleteConfirmationComponent } from "./user-settings-page/delete-confirmation/delete-confirmation.component";
import { BookPageComponent } from "./pages/book-page/book-page.component";
import { SeriesPageComponent } from "./pages/series-page/series-page.component";
import { MarkdownModule } from "ngx-markdown";
import { AuthUserService } from "./services/authentication/auth-user.service";

@NgModule({
declarations: [
Expand Down Expand Up @@ -51,7 +51,7 @@ import { MarkdownModule } from "ngx-markdown";
BookPageComponent,
SeriesPageComponent
],
providers: [Title, LocalCookiesService],
providers: [Title, AuthUserService],
bootstrap: [AppComponent]
})
export class AppModule {}
9 changes: 9 additions & 0 deletions src/app/constants/UserPermissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export enum UserPermissions {
APPROVE_CORRECTIONS = "approve_corrections",
VIEW_CORRECTIONS = "view_corrections",
UPDATE_USERS = "update_users",
ADD_ENTRY = "add_entry",
DELETE_ENTRY = "delete_entry",
MODIFY_ENTRY = "modify_entry",
STAFF = "staff"
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { inject } from "@angular/core";
import { Router } from "@angular/router";
import { tap } from "rxjs";
import { AuthenticationService } from "./authentication.service";
import { AuthenticationService } from "../services/authentication/authentication.service";

export const AuthenticationGuard = () => {
const router = inject(Router);
const authService = inject(AuthenticationService);

return authService.isLoggedIn().pipe(
return authService.validateCookies().pipe(
tap((value) => {
return value ? true : router.navigate(["/login"], { queryParams: { state: "expired" } });
})
Expand Down
7 changes: 7 additions & 0 deletions src/app/models/AuthUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface AuthUser {
user_id: number;
username: string;
create_date: string;
last_login: string;
role_name: string;
}
14 changes: 7 additions & 7 deletions src/app/pages/book-page/book-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { MetadataService } from "../../services/metadata.service";
import { MynewormAPIService } from "../../services/myneworm-api.service";
import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
import { ListEntryModalComponent } from "../../shared/list-entry-modal/list-entry-modal.component";
import { LocalCookiesService } from "../../services/authentication/local-cookies.service";
import { ListEntry } from "../../models/ListEntry";
import { ToastService } from "../../services/toast.service";
import { CommonModule } from "@angular/common";
Expand All @@ -16,6 +15,7 @@ import { BookFormatPipe } from "src/app/pipes/BookFormat.pipe";
import { SharedModule } from "src/app/shared/shared.module";
import * as moment from "moment";
import { MarkdownModule } from "ngx-markdown";
import { AuthUserService } from "src/app/services/authentication/auth-user.service";

@Component({
selector: "book-page",
Expand All @@ -28,7 +28,7 @@ export class BookPageComponent implements OnInit {
book: BookData;
publisher: PublisherData;
isLoggedIn = false;
private userID: string;
private userID: number;
hasExistingEntry = false;
remainingMsg: string;

Expand All @@ -37,14 +37,14 @@ export class BookPageComponent implements OnInit {
private service: MynewormAPIService,
private metaService: MetadataService,
private matDialog: MatDialog,
private cookieService: LocalCookiesService,
private AuthUser: AuthUserService,
private toastService: ToastService,
private router: Router
) {
this.cookieService.userEvent.subscribe((value) => {
this.isLoggedIn = Object.keys(value).length > 0;
this.AuthUser.userEvent.subscribe((value) => {
this.isLoggedIn = this.AuthUser.isLoggedIn();

if (this.isLoggedIn) {
if (this.isLoggedIn && value !== null) {
this.userID = value.user_id;
}
});
Expand Down Expand Up @@ -75,7 +75,7 @@ export class BookPageComponent implements OnInit {

if (this.isLoggedIn) {
this.service
.getListEntry(data.isbn, this.userID)
.getListEntry(data.isbn, this.userID.toString())
.pipe(
catchError((err) => {
if (err.status === 404) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { TestBed } from "@angular/core/testing";

import { LocalCookiesService } from "./local-cookies.service";
import { AuthUserService } from "./auth-user.service";

describe("LocalCookiesService", () => {
let service: LocalCookiesService;
describe("AuthUserService", () => {
let service: AuthUserService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LocalCookiesService);
service = TestBed.inject(AuthUserService);
});

it("should be created", () => {
Expand Down
66 changes: 66 additions & 0 deletions src/app/services/authentication/auth-user.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { AuthUser } from "../../models/AuthUser";
import { UserPermissions } from "../../constants/UserPermissions";

@Injectable({
providedIn: "root"
})
export class AuthUserService {
userEvent = new BehaviorSubject<AuthUser | null>(null);
user: AuthUser | null = null;
private userPermissions: string[];

constructor() {
this.userEvent.subscribe((value) => {
this.user = value;
});

const cachedAuth = localStorage.getItem("user");

if (cachedAuth) {
this.user = JSON.parse(cachedAuth);
}
this.userEvent.next(this.user);
}

isLoggedIn() {
return this.user !== null;
}

isModerator() {
return this.user !== null && this.userPermissions.includes(UserPermissions.STAFF);
}

isSameUser(username: string) {
return this.user !== null && this.user.username === username;
}

setPermissions(permissions: UserPermissions[]) {
this.userPermissions = permissions;
}

hasPermission(...permissions: UserPermissions[]) {
for (let i = 0; i < permissions.length; i++) {
if (!this.userPermissions.includes(permissions[i])) {
return false;
}
}
return true;
}

updateUser(userObj: any) {
this.userPermissions = userObj["permissions"];
delete userObj["permissions"];
this.user = userObj;
localStorage.setItem("user", JSON.stringify(userObj));
this.userEvent.next(this.user);
}

deleteUser() {
localStorage.removeItem("user");
this.user = null;
this.userPermissions = [];
this.userEvent.next(this.user);
}
}
44 changes: 10 additions & 34 deletions src/app/services/authentication/authentication.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { Injectable } from "@angular/core";
import { catchError, map, of } from "rxjs";
import { environment } from "src/environments/environment";
import { Buffer } from "buffer";
import { LocalCookiesService } from "./local-cookies.service";
import { ToastService } from "../toast.service";
import { AuthUserService } from "./auth-user.service";

@Injectable({
providedIn: "root"
})
export class AuthenticationService {
constructor(
private http: HttpClient,
private cookieService: LocalCookiesService,
private toastService: ToastService
private toastService: ToastService,
private AuthUserService: AuthUserService
) {}

login(username: string, password: string) {
Expand All @@ -36,7 +36,7 @@ export class AuthenticationService {
if (data.body !== null) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.cookieService.updateUser(data.body.user);
this.AuthUserService.updateUser(data.body.user);
return true;
}

Expand All @@ -54,7 +54,7 @@ export class AuthenticationService {
validateCookies() {
return this.http
.post(
`${environment.API_ADDRESS}/auth/validateCookies`,
`${environment.API_ADDRESS}/auth/validate`,
{},
{
withCredentials: true,
Expand All @@ -63,40 +63,16 @@ export class AuthenticationService {
)
.pipe(
map((data) => {
this.cookieService.updateUser(data.body);
this.AuthUserService.updateUser(data.body);
return true;
}),
catchError(() => {
this.cookieService.deleteUser();
this.AuthUserService.deleteUser();
return of(false);
})
);
}

isLoggedIn() {
return this.http
.post(
`${environment.API_ADDRESS}/auth/isAuthenticated`,
{},
{
withCredentials: true,
observe: "response"
}
)
.pipe(
map((data) => {
return data.status === 200;
}),
catchError((error) => {
if (error.status === 401) {
this.cookieService.deleteUser();
return of(false);
}
return of(`ERROR (${error.status}): ${error.statusText}`);
})
);
}

reauthenticate() {
return this.http
.post(
Expand Down Expand Up @@ -136,7 +112,7 @@ export class AuthenticationService {
}

clearSessions() {
this.cookieService.deleteUser();
this.AuthUserService.deleteUser();
return this.http.post(`${environment.API_ADDRESS}/auth/clear`, {}).pipe(
catchError((err: any) => {
this.toastService.sendError(err.error.errors);
Expand All @@ -157,12 +133,12 @@ export class AuthenticationService {
)
.pipe(
map((data) => {
this.cookieService.deleteUser();
this.AuthUserService.deleteUser();
return data.status === 200;
}),
catchError((error) => {
if (error.status === 401) {
this.cookieService.deleteUser();
this.AuthUserService.deleteUser();
return of(false);
}
return of(`ERROR (${error.status}): ${error.statusText}`);
Expand Down
Loading

0 comments on commit 70efbca

Please sign in to comment.