Commit 1043b35e by sawit

permission

parent 09a9899a
export type PermissionModel = PermissionModel2[]
export interface PermissionModel2 {
employeeId: string
bossId: string
fname: string
lname: string
efname: string
elname: string
bu1: Bu1
bu2: Bu2
bu3: Bu3
bu4: Bu4
bu5: Bu5
bu6: Bu6
bu7: Bu7
position: Position
pl: Pl
picture: string
busNo: string
status: Status
}
export interface Bu1 {
bu1id: string
tdesc: string
edesc: string
}
export interface Bu2 {
bu2id: string
tdesc: string
edesc: string
parent: any
}
export interface Bu3 {
bu3id: string
tdesc: string
edesc: string
parent: any
}
export interface Bu4 {
bu4id: string
tdesc: string
edesc: string
parent: any
}
export interface Bu5 {
bu5id: string
tdesc: string
edesc: string
parent: any
}
export interface Bu6 {
bu6id: string
tdesc: string
edesc: string
parent: any
}
export interface Bu7 {
bu7id: string
tdesc: string
edesc: string
parent: any
}
export interface Position {
positionId: string
tdesc: string
edesc: string
consolidate: any
shortName: any
}
export interface Pl {
plId: string
tdesc: string
edesc: string
}
export interface Status {}
<div class="container mx-auto p-4" *ngIf="role$ | async as role">
<h1 class="text-2xl font-bold mb-1">{{ 'EDIT_PERMISSIONS' | translate }}</h1>
<h2 class="text-lg text-gray-600 mb-6">{{ 'ROLE' | translate }}: <span class="font-semibold">{{ role.name }}</span></h2>
<div class="bg-white rounded-lg shadow-md p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div *ngFor="let app of (applications$ | async)" class="flex items-center justify-between p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<div>
<div class="font-semibold text-gray-800">{{ app.appName }}</div>
<div class="text-sm text-gray-500 mt-1">{{ app.description }}</div>
</div>
<mat-slide-toggle
[checked]="rolePermission.permissions[app.appId]"
(change)="onPermissionChange(app.appId, $event.checked)"
color="primary">
</mat-slide-toggle>
</div>
</div>
<div class="flex justify-end mt-8">
<button mat-stroked-button (click)="cancel()" class="mr-2">{{ 'CANCEL' | translate }}</button>
<button mat-flat-button color="primary" (click)="savePermissions()">{{ 'SAVE_CHANGES' | translate }}</button>
</div>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AppPermission, Role, RolePermission } from '../permission.model';
import { PermissionService } from '../permission.service';
// Core Angular & Material imports
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatButtonModule } from '@angular/material/button';
// Translation
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'app-permission-edit',
standalone: true,
imports: [
CommonModule,
FormsModule,
MatSlideToggleModule,
MatButtonModule,
TranslateModule
],
templateUrl: './permission-edit.component.html',
styleUrls: ['./permission-edit.component.scss']
})
export class PermissionEditComponent implements OnInit {
roleId!: string;
role$!: Observable<Role | undefined>;
applications$!: Observable<AppPermission[]>;
rolePermission: RolePermission = { roleId: '', permissions: {} };
constructor(
private route: ActivatedRoute,
private router: Router,
private permissionService: PermissionService
) { }
ngOnInit(): void {
this.roleId = this.route.snapshot.paramMap.get('roleId')!;
this.rolePermission.roleId = this.roleId;
this.role$ = this.permissionService.getRoles().pipe(
map(roles => roles.find(r => r.id === this.roleId))
);
this.applications$ = this.permissionService.getApplications();
this.permissionService.getRolePermissions(this.roleId).subscribe(permissions => {
if (permissions) {
this.rolePermission = permissions;
}
});
}
onPermissionChange(appId: string, isChecked: boolean): void {
this.rolePermission.permissions[appId] = isChecked;
}
savePermissions(): void {
this.permissionService.updateRolePermission(this.rolePermission).subscribe(() => {
this.router.navigate(['/portal-manage/permission-management']);
});
}
cancel(): void {
this.router.navigate(['/portal-manage/permission-management']);
}
}
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { PermissionEmployeelistComponent } from './permission-employeelist.component';
describe('PermissionEmployeelistComponent', () => {
let component: PermissionEmployeelistComponent;
let fixture: ComponentFixture<PermissionEmployeelistComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PermissionEmployeelistComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PermissionEmployeelistComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">{{ 'ROLE_BASED_ACCESS_CONTROL' | translate }}</h1>
<div *ngIf="roles$ | async as roles" class="mat-elevation-z8 bg-white rounded-lg overflow-hidden">
<table mat-table [dataSource]="roles" class="w-full">
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef class="p-4 text-left text-sm font-semibold text-gray-600 uppercase tracking-wider">{{ 'ROLE_NAME' | translate }}</th>
<td mat-cell *matCellDef="let role" class="p-4 whitespace-nowrap text-sm text-gray-800"> {{role.name}} </td>
</ng-container>
<!-- Description Column -->
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef class="p-4 text-left text-sm font-semibold text-gray-600 uppercase tracking-wider">{{ 'DESCRIPTION' | translate }}</th>
<td mat-cell *matCellDef="let role" class="p-4 text-sm text-gray-500"> {{role.description}} </td>
</ng-container>
<!-- Actions Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="p-4 text-left text-sm font-semibold text-gray-600 uppercase tracking-wider">{{ 'ACTIONS' | translate }}</th>
<td mat-cell *matCellDef="let role" class="p-4 whitespace-nowrap text-sm font-medium">
<button mat-icon-button color="primary" (click)="navigateToEdit(role.id)" [attr.aria-label]="'EDIT_PERMISSIONS' | translate">
<mat-icon>edit</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Role } from '../permission.model';
import { PermissionService } from '../permission.service';
import { Router, RouterModule } from '@angular/router';
// Core Angular & Material imports
import { CommonModule } from '@angular/common';
import { MatTableModule } from '@angular/material/table';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
// Translation
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'app-permission-list',
standalone: true,
imports: [
CommonModule,
RouterModule,
MatTableModule,
MatButtonModule,
MatIconModule,
TranslateModule
],
templateUrl: './permission-list.component.html',
styleUrls: ['./permission-list.component.scss']
})
export class PermissionListComponent implements OnInit {
roles$!: Observable<Role[]>;
displayedColumns: string[] = ['name', 'description', 'actions'];
constructor(
private permissionService: PermissionService,
private router: Router
) { }
ngOnInit(): void {
this.roles$ = this.permissionService.getRoles();
}
navigateToEdit(roleId: string): void {
this.router.navigate(['/portal-manage/permission-management/edit', roleId]);
}
}
import { Routes } from '@angular/router';
import { PermissionListComponent } from './permission-list/permission-list.component';
import { PermissionEditComponent } from './permission-edit/permission-edit.component';
import { PermissionEmployeelistComponent } from './permission-employeelist/permission-employeelist.component';
export const PERMISSION_ROUTES: Routes = [
{
path: '',
component: PermissionListComponent,
pathMatch: 'full',
data: { title: 'Permission Management' }
},
{
path: 'edit/:roleId',
component: PermissionEditComponent,
data: { title: 'Edit Permissions' }
component: PermissionEmployeelistComponent,
children: [
{
path: 'permission-employeelist',
loadComponent: () =>
import('./permission-employeelist/permission-employeelist.component').then((m) => m.PermissionEmployeelistComponent),
},
]
}
];
import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({
providedIn: 'root'
})
export class EncodeCyptoService {
tokenFromUI: string = "S3c5et@3$#m7H5MYHRPLUS@SERVICE$KEYPASS";
encrypted: any = "";
decrypted: any = "";
constructor() { }
encryptUsingAES256(plainText: string) {
// var salt = CryptoJS.lib.WordArray.random(128 / 8);
// var key = this.generateKey(salt, this.tokenFromUI);
// var iv = CryptoJS.lib.WordArray.random(128 / 8);
// var encrypted = CryptoJS.AES.encrypt(
// plainText,
// key, {
// iv: iv,
// padding: CryptoJS.pad.Pkcs7,
// mode: CryptoJS.mode.CBC
// });
// var swap_encrypted = encrypted.toString().replace(/\+/g, 'xMl3Jk').replace(/\//g, 'Por21Ld').replace(/\=/g, 'Ml32')
// this.encrypted = salt.toString() + iv.toString() + swap_encrypted;
return plainText
}
decryptUsingAES256(plainText: string) {
// var salt =CryptoJS.enc.Hex.parse(plainText.substr(0, 32));
// var iv = CryptoJS.enc.Hex.parse(plainText.substr(32, 32));
// var _encrypted = plainText.substring(64);
// var swap_encrypted=_encrypted.toString().replace(/\xMl3Jk/g,'+').replace(/\Por21Ld/g,'/').replace(/\Ml32/g,'=');
// var key = this.generateKey(salt, this.tokenFromUI);
// this.decrypted = CryptoJS.AES.decrypt(swap_encrypted, key, {
// iv: iv,
// padding: CryptoJS.pad.Pkcs7,
// mode: CryptoJS.mode.CBC
// }).toString(CryptoJS.enc.Utf8);
// console.log("decrpted",this.decrypted)
return plainText
}
generateKey(salt, passPhrase) {
let keySize = 256 / 32;
let iterationCount = 100;
var key = CryptoJS.PBKDF2(passPhrase, salt,
{ keySize: keySize, iterations: iterationCount });
return key;
}
}
import { Permission } from './../../models/user-role.model';
import { Injectable } from '@angular/core';
import { environment } from '../../../../environments/environment';
import { Observable, zip } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
import { map, tap } from 'rxjs/operators';
import {EncodeCyptoService} from './encode-cypto.service';
import {PermissionModel} from './../../models/permission/permission.model';
@Injectable({
providedIn: 'root'
})
export class PermissionService {
lang: string = "";
urlApiplus: string = "https://hrplus.myhr.co.th/plus";
private BASE_PATH: string = this.urlApiplus + '/dashboard';
private uprofile: Observable<PermissionModel> | undefined;
urlApi = this.urlApiplus
constructor(
private http: HttpClient,
private router: Router,
private translateService: TranslateService,
private datePipe: DatePipe,
private cyptoService: EncodeCyptoService
) { }
getListEmpWorkingObserve(sizePage: number, page: number): Observable<PermissionModel[]> {
return this.http
.get<PermissionModel[]>(
this.urlApi + '/employee/workings/mini?page=' + page + '&size=' + sizePage
)
}
}
......@@ -293,7 +293,7 @@ export class SidebarComponent {
} else if (this.isMenuPermissionManagementRoute){
this.menuItems = this.navServices.getSystemManagementMenu();
} else if (this.isMeetingBookingRoute){
this.menuItems = this.navServices.getSystemManagementMenu();
this.menuItems = this.navServices.getMeetingBookingMenu();
} else if (this.isWidgetWarehouseRoute || this.isWidgetLinkerRoute){
// สำหรับ widget-warehouse และ widget-linker ใช้เมนูตามแอปที่อยู่ใน URL
const appName = this.extractAppNameFromUrl(this.currentUrl);
......
......@@ -36,6 +36,10 @@ export class HttpRequestInterceptor {
token = `Bearer ${this.tokenService.getAppToken()}`;
}
if (fullUrl.startsWith('https://hrplus.myhr.co.th')) {
token = `Bearer ${this.tokenService.getToken()}`;
}
let authReq = req.clone({ url: fullUrl });
if (token) {
......
......@@ -464,44 +464,31 @@ export class NavService implements OnDestroy {
return [
{ headTitle: 'การตั้งค่าระบบ' },
{
title: 'my-Portal',
icon: 'upload-cloud',
path: '/portal-manage/my-portal',
type: 'link',
},
{
title: 'จัดการสิทธิ์',
icon: 'shield',
type: 'sub',
active: false,
children: [
{ path: '/portal-manage/permission-management', title: 'จัดการสิทธิ์และบทบาท', type: 'link' },
{ path: '/portal-manage/menu-permission-management', title: 'จัดการสิทธิ์เมนู', type: 'link' },
{ path: '/portal-manage/user-role-management', title: 'จัดการผู้ใช้และบทบาท', type: 'link' },
],
},
{
title: 'จัดการแดชบอร์ดและวิดเจ็ต',
icon: 'dashboard',
type: 'sub',
active: false,
children: [
{ path: '/portal-manage/dashboard-management/dashboard-home', title: 'แดชบอร์ดหลัก', type: 'link' },
{ path: '/portal-manage/dashboard-management/widget-list', title: 'รายการวิดเจ็ต', type: 'link' },
{ path: '/portal-manage/dashboard-management/dataset-widget-linker', title: 'เชื่อมโยงข้อมูลกับวิดเจ็ต', type: 'link' },
{ path: '/portal-manage/dashboard-management/widget-config', title: 'ตั้งค่าวิดเจ็ต', type: 'link' },
{ path: '/portal-manage/dashboard-management/dashboard-viewer', title: 'ดูแดชบอร์ด', type: 'link' },
{ path: '/portal-manage/permission-management/permission-employeelist', title: 'จัดการสิทธิ์และบทบาท', type: 'link' },
// { path: '/portal-manage/menu-permission-management', title: 'จัดการสิทธิ์เมนู', type: 'link' },
// { path: '/portal-manage/user-role-management', title: 'จัดการผู้ใช้และบทบาท', type: 'link' },
],
},
];
}
// เมนูสำหรับการจองห้องประชุม
getMeetingBookingMenu() {
return [
{ headTitle: 'ระบบจองห้องประชุม' },
{
title: 'การบริการ',
icon: 'service',
title: 'ระบบจองห้องประชุม',
icon: 'room-booking',
type: 'sub',
active: false,
children: [
{ path: '/portal-manage/meeting-booking', title: 'จองห้องประชุม', type: 'link' },
],
}
},
];
}
......@@ -595,11 +582,12 @@ export class NavService implements OnDestroy {
case 'dashboard-management':
return this.getDashboardManagementMenu();
case 'meeting-booking':
return this.getSystemManagementMenu();
return this.getMeetingBookingMenu();
case 'permission-management':
case 'menu-permission-management':
case 'user-role-management':
return this.getSystemManagementMenu();
// case 'menu-permission-management':
// case 'user-role-management':
// return this.getSystemManagementMenu();
default:
return [];
}
......@@ -619,10 +607,10 @@ export class NavService implements OnDestroy {
'company-management': this.getCompanyMenu(),
'dashboard': this.getDashboardMenu(),
'dashboard-management': this.getDashboardManagementMenu(),
'meeting-booking': this.getSystemManagementMenu(),
'meeting-booking': this.getMeetingBookingMenu(),
'permission-management': this.getSystemManagementMenu(),
'menu-permission-management': this.getSystemManagementMenu(),
'user-role-management': this.getSystemManagementMenu(),
// 'menu-permission-management': this.getSystemManagementMenu(),
// 'user-role-management': this.getSystemManagementMenu(),
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment