76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
"use client";
 | 
						|
 | 
						|
import axios from "axios";
 | 
						|
import { Dispatch, SetStateAction } from "react";
 | 
						|
import { Subscription, interval } from "rxjs";
 | 
						|
 | 
						|
interface UserinfoDto {
 | 
						|
  username: string;
 | 
						|
  email: string;
 | 
						|
  roles: string[];
 | 
						|
  exp: number;
 | 
						|
}
 | 
						|
 | 
						|
export class User {
 | 
						|
  static readonly ANONYMOUS = new User("", "", []);
 | 
						|
 | 
						|
  constructor(
 | 
						|
    readonly name: string,
 | 
						|
    readonly email: string,
 | 
						|
    readonly roles: string[]
 | 
						|
  ) {}
 | 
						|
 | 
						|
  get isAuthenticated(): boolean {
 | 
						|
    return !!this.name;
 | 
						|
  }
 | 
						|
 | 
						|
  hasAnyRole(...roles: string[]): boolean {
 | 
						|
    for (const r of roles) {
 | 
						|
      if (this.roles.includes(r)) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export class UserService {
 | 
						|
  private refreshSub?: Subscription;
 | 
						|
 | 
						|
  constructor(user: User, setUser: Dispatch<SetStateAction<User>>) {
 | 
						|
    this.refresh(user, setUser);
 | 
						|
  }
 | 
						|
 | 
						|
  async refresh(
 | 
						|
    user: User,
 | 
						|
    setUser: Dispatch<SetStateAction<User>>
 | 
						|
  ): Promise<void> {
 | 
						|
    this.refreshSub?.unsubscribe();
 | 
						|
    const response = await axios.get<UserinfoDto>("/bff/api/me");
 | 
						|
    if (
 | 
						|
      response.data.username !== user.name ||
 | 
						|
      response.data.email !== user.email ||
 | 
						|
      (response.data.roles || []).toString() !== user.roles.toString()
 | 
						|
    ) {
 | 
						|
      setUser(
 | 
						|
        response.data.username
 | 
						|
          ? new User(
 | 
						|
              response.data.username || "",
 | 
						|
              response.data.email || "",
 | 
						|
              response.data.roles || []
 | 
						|
            )
 | 
						|
          : User.ANONYMOUS
 | 
						|
      );
 | 
						|
    }
 | 
						|
    if (!!response.data.exp) {
 | 
						|
      const now = Date.now();
 | 
						|
      const delay = (1000 * response.data.exp - now) * 0.8;
 | 
						|
      if (delay > 2000) {
 | 
						|
        this.refreshSub = interval(delay).subscribe(() =>
 | 
						|
          this.refresh(user, setUser)
 | 
						|
        );
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |