Calendar event booking - namthuviec/microservice GitHub Wiki

Database

You can structure a PostgreSQL database table to store calendar event bookings with relevant details. Here's an example schema:

Table: event_bookings

Column Name Data Type Description
id SERIAL PRIMARY KEY Unique identifier for each event
project_name VARCHAR(255) Name of the associated project
start_date TIMESTAMP Event start date and time
end_date TIMESTAMP Event end date and time
note TEXT Additional details about the event

Example Query to Create Table

CREATE TABLE event_bookings (
    id SERIAL PRIMARY KEY,
    project_name VARCHAR(255) NOT NULL,
    start_date TIMESTAMP NOT NULL,
    end_date TIMESTAMP NOT NULL,
    note TEXT
);

Would you like help with queries to insert, update, or retrieve data from this structure? 🚀

You can create a projects table to store static project data and establish a relationship with the event_bookings table using a foreign key. Here's how you can structure it in PostgreSQL:

Table: projects

Column Name Data Type Description
id SERIAL PRIMARY KEY Unique identifier for each project
name VARCHAR(255) NOT NULL Name of the project
description TEXT Details about the project

Modify event_bookings to Link Projects

You'll want to replace project_name with a foreign key that references the projects table:

CREATE TABLE projects (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT
);

CREATE TABLE event_bookings ( id SERIAL PRIMARY KEY, project_id INT NOT NULL, start_date TIMESTAMP NOT NULL, end_date TIMESTAMP NOT NULL, note TEXT, FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE );

Now, each event booking is linked to a project by project_id. Would you like help with inserting data or retrieving it efficiently? 🚀

Frontend

You can use the React Calendar Library (like react-calendar or react-big-calendar) to build an interactive view for your event_bookings while allowing users to filter events by month, week, and day. Here’s how to get started:

1️⃣ Install Dependencies

Choose the library you want:

Option 1: react-calendar

npm install react-calendar

Option 2: react-big-calendar

npm install react-big-calendar moment

2️⃣ Create the Calendar Component

A basic setup using react-calendar for filtering views:

import React, { useState } from 'react';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';

const EventCalendar = ({ events }) => {
    const [date, setDate] = useState(new Date());

    const filteredEvents = events.filter(event => 
        new Date(event.start_date).toDateString() === date.toDateString()
    );

    return (
        <div>
            <Calendar onChange={setDate} value={date} />
            <h3>Events on {date.toDateString()}</h3>
            {filteredEvents.map(event => (
                <div key={event.id}>
                    <strong>{event.note}</strong> - {event.start_date}
                </div>
            ))}
        </div>
    );
};

export default EventCalendar;

3️⃣ Adding Month, Week, Day View with react-big-calendar

For more advanced filtering by month, week, or day, use react-big-calendar:

import React, { useState } from 'react';
import { Calendar, Views, momentLocalizer } from 'react-big-calendar';
import moment from 'moment';
import 'react-big-calendar/lib/css/react-big-calendar.css';

const localizer = momentLocalizer(moment);

const EventCalendar = ({ events }) => {
    const [view, setView] = useState(Views.MONTH);

    return (
        <div>
            <Calendar
                localizer={localizer}
                events={events}
                startAccessor="start_date"
                endAccessor="end_date"
                views={[Views.MONTH, Views.WEEK, Views.DAY]}
                defaultView={view}
                onView={(newView) => setView(newView)}
            />
        </div>
    );
};

export default EventCalendar;

4️⃣ Fetch Event Data from Your API

Modify your component to fetch event data from your Spring Boot API:

import { useEffect, useState } from 'react';

const fetchEvents = async () => {
    const response = await fetch('http://localhost:8080/api/events');
    const data = await response.json();
    return data.map(event => ({
        ...event,
        start_date: new Date(event.start_date),
        end_date: new Date(event.end_date),
    }));
};

useEffect(() => {
    fetchEvents().then(setEvents);
}, []);

5️⃣ Run the Application

Start your Spring Boot backend and React frontend, then test event filtering by switching between month, week, and day views.

Would you like to add features like event creation, editing, or color-coded event types? 🚀

Backend API

1. Application Type: monolithic

jhipster setup a application event_bookings, project type monolithic, database postgress, authenticate JWT, Generate Sprint Boot REST APIs, create JPA repositories, Frontend UI components ReactJS, Multi tenant, multi language

You're looking to set up a JHipster application with EventBookings and Projects, using a monolithic architecture, PostgreSQL, JWT authentication, Spring Boot REST APIs, JPA repositories, a ReactJS frontend, multi-tenancy, and multi-language support. Let’s break it down step by step 🚀.


1️⃣ Generate a JHipster Application

First, install JHipster:

npm install -g generator-jhipster

Create your new application:

mkdir event-booking-app && cd event-booking-app
jhipster

During the interactive setup, choose:

  • Application type: Monolithic
  • Database: PostgreSQL
  • Authentication: JWT
  • Frontend framework: React
  • Multi-language: ✅ (Select the languages you need)
  • Multi-tenancy: ✅ (Choose schema-based or row-based)

JHipster will generate your backend and frontend automatically! 🚀


2️⃣ Define Your Entities (EventBookings & Projects)

Use JHipster's entity generator to create them.

Create the Project Entity

jhipster entity Project

Define fields:

  • id (Auto-generated)
  • name (String, required)
  • description (Text)

Create the EventBooking Entity

jhipster entity EventBooking

Define fields:

  • id (Auto-generated)
  • startDate (Instant)
  • endDate (Instant)
  • note (Text)
  • project (Many-to-One relationship to Project)

JHipster will generate Spring Boot REST APIs, JPA repositories, and React UI components!


3️⃣ Implement Multi-Tenancy

JHipster does not support multi-tenancy out of the box, so you need to add tenant-based filtering.

Option 1: Schema-Based Multi-Tenancy (Separate Databases)

Modify your application.yml:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/{tenantDb}

Each tenant gets its own schema dynamically.

Option 2: Row-Based Multi-Tenancy (Shared Database)

Modify your entities:

@Entity
@Table(name = "projects")
public class Project {
    @Column(nullable = false)
    private String tenantId;  // Each tenant gets its own data
}

Modify repositories to filter by tenant:

@Repository
public interface ProjectRepository extends JpaRepository<Project, Long> {
    List<Project> findByTenantId(String tenantId);
}

4️⃣ Enable JWT Tenant Assignment

Modify TokenProvider.java to store tenant ID:

public class CustomTokenProvider extends TokenProvider {
    @Override
    public String createToken(Authentication authentication) {
        String tenantId = getTenantFromUser(authentication);
        return Jwts.builder()
            .setSubject(authentication.getName())
            .claim("tenantId", tenantId)
            .signWith(SignatureAlgorithm.HS512, secretKey)
            .compact();
    }
}

This ensures each tenant gets a unique token.


5️⃣ Configure Multi-Language Support

Modify i18n configuration in src/main/webapp/i18n.

Enable Multi-Language UI in React

import { useTranslation } from "react-i18next";

const MyComponent = () => {
    const { t } = useTranslation();
    return <h1>{t("welcome_message")}</h1>;
};

Edit src/main/webapp/i18n/en.json:

{
    "welcome_message": "Welcome to Event Booking App!"
}

Add other language JSON files (vi.json, fr.json, etc.).


6️⃣ Deploy & Run

Start the application:

./mvnw
npm start

Now you have multi-tenant, multi-language, React + Spring Boot, and JWT authentication in JHipster! 🚀

Would you like dynamic tenant creation or role-based permissions for event bookings? 😊

2. Application type: microservice

jhipster setup a application event_bookings, project type microservice, database postgress, authenticate JWT, Generate Sprint Boot REST APIs, create JPA repositories, Frontend UI components ReactJS, Multi tenant, multi language

Setting up a JHipster microservice application with EventBookings and Projects, using PostgreSQL, JWT authentication, Spring Boot REST APIs, JPA repositories, ReactJS frontend, multi-tenancy, and multi-language support requires multiple steps. Here's a complete setup guide 🚀.


1️⃣ Generate a JHipster Microservice

First, install JHipster globally:

npm install -g generator-jhipster

Create your gateway (React frontend + API gateway):

mkdir event-booking-gateway && cd event-booking-gateway
jhipster

During setup, select:

  • Application type: Microservice gateway
  • Database: PostgreSQL
  • Authentication: JWT
  • Frontend Framework: React
  • Multi-language support: ✅ (Choose your languages)
  • Multi-tenancy: ✅ (Schema-based or row-based)
  • Service Discovery: ✅ (Consul or JHipster Registry)

This will generate a React-based UI along with an API gateway.


2️⃣ Generate Microservices

Each microservice manages different entities (Projects & EventBookings).
Create the Project microservice:

mkdir project-service && cd project-service
jhipster

Choose:

  • Application type: Microservice
  • Database: PostgreSQL
  • Authentication: JWT
  • Service Discovery: Consul or JHipster Registry

Create the EventBooking microservice:

mkdir event-booking-service && cd event-booking-service
jhipster

Follow the same setup process.


3️⃣ Define Multi-Tenant Entities

Modify Projects and EventBookings to store tenant ID.

Projects Entity

@Entity
@Table(name = "projects")
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String description;

    @Column(nullable = false)
    private String tenantId;  // Each tenant's data is separated
}

EventBookings Entity

@Entity
@Table(name = "event_bookings")
public class EventBooking {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Instant startDate;
    private Instant endDate;
    private String note;

    @Column(nullable = false)
    private String tenantId;
}

4️⃣ Configure Multi-Tenancy

Row-Based Multi-Tenancy (Shared Database)

Modify repositories to filter queries by tenant ID:

@Repository
public interface ProjectRepository extends JpaRepository<Project, Long> {
    List<Project> findByTenantId(String tenantId);
}

@Repository
public interface EventBookingRepository extends JpaRepository<EventBooking, Long> {
    List<EventBooking> findByTenantId(String tenantId);
}

Schema-Based Multi-Tenancy (Separate Databases)

Modify application.yml to dynamically switch tenants:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/{tenantDb}

5️⃣ Enable JWT Tenant Assignment

Modify TokenProvider.java to store tenantId:

@Override
public String createToken(Authentication authentication) {
    User user = (User) authentication.getPrincipal();
    String tenantId = user.getTenantId();

    return Jwts.builder()
        .setSubject(user.getUsername())
        .claim("tenantId", tenantId)
        .signWith(SignatureAlgorithm.HS512, secretKey)
        .compact();
}

6️⃣ Setup Multi-Language Support

Modify i18n configuration in the gateway-service.

Enable Multi-Language in React

import { useTranslation } from "react-i18next";

const MyComponent = () => {
    const { t } = useTranslation();
    return <h1>{t("welcome_message")}</h1>;
};

Edit src/main/webapp/i18n/en.json:

{
    "welcome_message": "Welcome to Event Booking!"
}

Add other language files (vi.json, fr.json, etc.).


7️⃣ Deploy & Run

Start Consul (or JHipster Registry), then run the services:

docker-compose up -d

Start each microservice:

cd project-service && ./mvnw
cd event-booking-service && ./mvnw
cd event-booking-gateway && npm start

Your multi-tenant microservice architecture is live! 🎉

Would you like to automate tenant creation or add role-based permissions? 😊

3. add role-based permissions

Adding role-based permissions to your JHipster microservice architecture ensures that different users (e.g., Admin, User, Tenant Owner) have restricted access to specific functionalities. Here’s how you can configure RBAC (Role-Based Access Control) in JHipster:


1️⃣ Define User Roles

JHipster uses Spring Security with JWT authentication, so you need to set up roles.

Modify AuthoritiesConstants.java:

public final class AuthoritiesConstants {
    public static final String ADMIN = "ROLE_ADMIN";
    public static final String USER = "ROLE_USER";
    public static final String TENANT_OWNER = "ROLE_TENANT_OWNER";
}

Now, users can be assigned these roles!


2️⃣ Assign Roles to Users

Modify User.java:

@ManyToMany
@JoinTable(
    name = "jhi_user_authority",
    joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "authority_name", referencedColumnName = "name")
)
private Set<Authority> authorities = new HashSet<>();

3️⃣ Secure API Endpoints

Restrict Admin, User, and Tenant Owner permissions in SecurityConfiguration.java:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests()
            .requestMatchers("/api/admin/**").hasRole("ADMIN") // Admin Only
            .requestMatchers("/api/tenants/**").hasRole("TENANT_OWNER") // Tenant Owner Only
            .requestMatchers("/api/events/**").hasAnyRole("USER", "TENANT_OWNER") // General Access
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        
        return http.build();
    }
}

This ensures only authorized users can access certain endpoints.


4️⃣ Assign Roles via API

Create an Admin API to manage role assignments dynamically:

@RestController
@RequestMapping("/api/admin")
public class RoleController {

    @Autowired
    private UserRepository userRepository;

    @PostMapping("/assign-role")
    public ResponseEntity<User> assignRole(@RequestParam String username, @RequestParam String role) {
        User user = userRepository.findOneByLogin(username).orElseThrow();
        user.getAuthorities().add(new Authority(role));
        userRepository.save(user);
        return ResponseEntity.ok(user);
    }
}

Now, Admin users can assign roles to other users via API.


5️⃣ Deploy & Test

  • Start the backend (./mvnw)
  • Use Postman or cURL to send test requests

✅ Example API calls:

  • POST /api/admin/assign-role?username=johndoe&role=ROLE_TENANT_OWNER
  • Restrict EventBooking management to only TENANT_OWNER

Would you like dynamic tenant role creation or custom JWT claims for roles? 🚀

4. dynamic tenant role creation

Dynamic tenant role creation allows each tenant to manage its own set of roles within your multi-tenant JHipster microservice. This means tenants can create custom roles, assign permissions, and manage users dynamically. Here’s how to implement it:


1️⃣ Modify Database Schema for Dynamic Roles

Each tenant should have its own set of roles. Modify the Authority entity:

@Entity
@Table(name = "tenant_roles")
public class TenantRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String roleName; // Custom role (e.g., "MANAGER", "SUPERVISOR")

    @Column(nullable = false)
    private String tenantId; // Role belongs to a specific tenant
}

Now, each tenant can define its own roles instead of using the global ones.


2️⃣ Create a Dynamic Role Service

Define a service that creates tenant-specific roles:

@Service
public class TenantRoleService {

    @Autowired
    private TenantRoleRepository roleRepository;

    public TenantRole createRole(String roleName, String tenantId) {
        TenantRole role = new TenantRole();
        role.setRoleName(roleName);
        role.setTenantId(tenantId);
        return roleRepository.save(role);
    }

    public List<TenantRole> getRolesByTenant(String tenantId) {
        return roleRepository.findByTenantId(tenantId);
    }
}

This ensures each tenant only manages its own roles.


3️⃣ Expose an API for Role Management

Create endpoints for role creation and fetching roles per tenant:

@RestController
@RequestMapping("/api/tenants/{tenantId}/roles")
public class TenantRoleController {

    @Autowired
    private TenantRoleService roleService;

    @PostMapping("/create")
    public ResponseEntity<TenantRole> createRole(@PathVariable String tenantId, @RequestParam String roleName) {
        TenantRole role = roleService.createRole(roleName, tenantId);
        return ResponseEntity.ok(role);
    }

    @GetMapping
    public List<TenantRole> getRoles(@PathVariable String tenantId) {
        return roleService.getRolesByTenant(tenantId);
    }
}

Now, each tenant can create and manage their own roles dynamically.


4️⃣ Integrate Role-Based Security for Tenants

Modify SecurityConfiguration.java to apply tenant-specific permissions:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests()
            .requestMatchers("/api/tenants/{tenantId}/roles/create").hasAuthority("TENANT_ADMIN")
            .requestMatchers("/api/events/**").hasAnyAuthority("TENANT_USER", "TENANT_MANAGER")
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        
        return http.build();
    }
}

Now, tenants only access features they have permission for.


5️⃣ Deploy & Test

Start your microservices and gateway, then test role creation:

Create a Role for a Tenant

POST /api/tenants/TENANT1/roles/create?roleName=SUPERVISOR

Fetch Roles for a Tenant

GET /api/tenants/TENANT1/roles

Now, each tenant has full control over its own role structure! 🚀
Would you like dynamic permissions for API access? 😊

5. dynamic permissions for API access

Dynamic permissions for API access allow you to control user roles and permissions at runtime, rather than hardcoding them in your security configuration. This is useful for multi-tenant systems, role-based access control (RBAC), and fine-grained API security.


1️⃣ Database Schema for Dynamic Permissions

Modify your TenantRole entity to support API permissions dynamically:

@Entity
@Table(name = "tenant_roles")
public class TenantRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String roleName;  // e.g., "MANAGER", "SUPERVISOR"
    private String tenantId;  // Each role belongs to a tenant

    @ElementCollection
    private Set<String> allowedEndpoints;  // Dynamic permissions per role
}

Now, each tenant role can define which APIs it can access.


2️⃣ API to Manage Permissions Dynamically

Create a REST API so tenants can manage role permissions.

@RestController
@RequestMapping("/api/tenants/{tenantId}/roles")
public class TenantRoleController {

    @Autowired
    private TenantRoleService roleService;

    @PostMapping("/create")
    public ResponseEntity<TenantRole> createRole(@PathVariable String tenantId, @RequestParam String roleName) {
        TenantRole role = roleService.createRole(roleName, tenantId);
        return ResponseEntity.ok(role);
    }

    @PostMapping("/{roleName}/permissions")
    public ResponseEntity<TenantRole> updatePermissions(
        @PathVariable String tenantId, @PathVariable String roleName, @RequestBody Set<String> endpoints) {
        
        TenantRole role = roleService.updateRolePermissions(tenantId, roleName, endpoints);
        return ResponseEntity.ok(role);
    }
}

Now, each tenant can create roles and define API permissions dynamically!


3️⃣ Implement Role-Based Security with Dynamic Permissions

Modify SecurityConfiguration.java to check permissions dynamically:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired
    private TenantRoleRepository roleRepository;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((auth) -> auth
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().access((authentication, context) -> {
                String tenantId = TenantContext.getTenantId();
                String userRole = getUserRole(authentication);

                Set<String> allowedEndpoints = roleRepository.findPermissionsByTenantAndRole(tenantId, userRole);

                return allowedEndpoints.contains(context.getRequest().getRequestURI()) ? 
                    new AuthorizationDecision(true) : new AuthorizationDecision(false);
            })
        );

        return http.build();
    }
}

Now, API access is checked dynamically based on user role and tenant permissions! 🎯


4️⃣ Deploy & Test

Start your microservices and gateway, then test role creation and API access:

Create a Role for a Tenant

POST /api/tenants/TENANT1/roles/create?roleName=MANAGER

Assign API Permissions to Role

POST /api/tenants/TENANT1/roles/MANAGER/permissions
Body: ["api/events", "api/projects"]

Ensure Role Can Access Only Assigned APIs Now, users with MANAGER role can only access api/events and api/projects, and nothing else.

Would you like to integrate custom OAuth2 claims for roles or build an admin UI for role management? 🚀

6. custom OAuth2 claims for roles

Integrating custom OAuth2 claims for roles allows you to embed role-based access control (RBAC) directly into your authentication system. This is useful for multi-tenant applications where different tenants may have different roles and permissions.


1️⃣ Modify JWT Token to Include Custom Claims

OAuth2 uses JWT for authentication, so modify your token creation logic to include roles dynamically.

Modify CustomTokenProvider.java to Add Role Claims

@Override
public String createToken(Authentication authentication) {
    User user = (User) authentication.getPrincipal();
    String tenantId = user.getTenantId();
    Set<String> roles = user.getAuthorities().stream()
                            .map(GrantedAuthority::getAuthority)
                            .collect(Collectors.toSet());

    return Jwts.builder()
        .setSubject(user.getUsername())
        .claim("tenantId", tenantId)  // Store Tenant ID
        .claim("roles", roles)  // Add Roles to JWT Token
        .signWith(SignatureAlgorithm.HS512, secretKey)
        .compact();
}

Now, every JWT token issued will include roles as a claim.


2️⃣ Extract Role Claims During Authentication

Modify OAuth2 Resource Server to retrieve roles from the JWT token.

@Override
public Authentication getAuthentication(String token) {
    Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
    
    String tenantId = claims.get("tenantId", String.class);
    List<String> roles = claims.get("roles", List.class);

    TenantContext.setTenantId(tenantId);  // Store Tenant ID in Context

    List<GrantedAuthority> authorities = roles.stream()
        .map(SimpleGrantedAuthority::new)
        .collect(Collectors.toList());

    return new UsernamePasswordAuthenticationToken(claims.getSubject(), null, authorities);
}

This ensures that roles are dynamically assigned based on the token claims.


3️⃣ Apply Role-Based Security Using OAuth2 Claims

Modify SecurityConfiguration.java to enforce RBAC dynamically:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((auth) -> auth
            .requestMatchers("/api/admin/**").hasAuthority("ROLE_ADMIN")
            .requestMatchers("/api/tenants/**").hasAuthority("ROLE_TENANT_OWNER")
            .requestMatchers("/api/events/**").hasAnyAuthority("ROLE_USER", "ROLE_TENANT_OWNER")
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        
        return http.build();
    }
}

Now, API access is controlled dynamically based on roles stored inside JWT.


4️⃣ Test & Deploy

Generate JWT with Roles

POST /api/authenticate
Response JWT:
{
  "tenantId": "TENANT1",
  "roles": ["ROLE_USER", "ROLE_TENANT_OWNER"]
}

Access APIs Based on Roles

GET /api/admin  # Only accessible to ROLE_ADMIN
GET /api/events # Accessible to ROLE_USER, ROLE_TENANT_OWNER

Would you like to integrate tenant-specific claims or custom permissions per tenant role? 🚀

7. custom permissions per tenant role

Setting up custom permissions per tenant role allows each tenant to define and control fine-grained access to their own resources. Here's how to implement tenant-specific permissions dynamically in a JHipster microservice architecture.


1️⃣ Extend the Tenant Role Entity

Modify the TenantRole entity to support permissions per role:

@Entity
@Table(name = "tenant_roles")
public class TenantRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String roleName;  // e.g., "MANAGER", "SUPERVISOR"

    @Column(nullable = false)
    private String tenantId;  // Role belongs to a specific tenant

    @ElementCollection
    private Set<String> allowedActions;  // Dynamic permissions per role
}

Now, each role within a tenant can have a unique set of allowed actions (e.g., "CREATE_EVENT", "EDIT_PROJECT").


2️⃣ Create a Dynamic Permission Management API

Expose endpoints for tenants to assign role permissions dynamically.

@RestController
@RequestMapping("/api/tenants/{tenantId}/roles")
public class TenantRoleController {

    @Autowired
    private TenantRoleService roleService;

    @PostMapping("/{roleName}/permissions")
    public ResponseEntity<TenantRole> updatePermissions(
        @PathVariable String tenantId, @PathVariable String roleName, @RequestBody Set<String> actions) {
        
        TenantRole role = roleService.updateRolePermissions(tenantId, roleName, actions);
        return ResponseEntity.ok(role);
    }

    @GetMapping("/{roleName}/permissions")
    public ResponseEntity<Set<String>> getRolePermissions(@PathVariable String tenantId, @PathVariable String roleName) {
        Set<String> permissions = roleService.getPermissionsForRole(tenantId, roleName);
        return ResponseEntity.ok(permissions);
    }
}

Now, tenants can update and retrieve permissions dynamically.


3️⃣ Implement Role-Based Security Using Dynamic Permissions

Modify SecurityConfiguration.java to check permissions per role dynamically:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Autowired
    private TenantRoleRepository roleRepository;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((auth) -> auth
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().access((authentication, context) -> {
                String tenantId = TenantContext.getTenantId();
                String userRole = getUserRole(authentication);

                Set<String> allowedActions = roleRepository.findPermissionsByTenantAndRole(tenantId, userRole);

                return allowedActions.contains(context.getRequest().getRequestURI()) ? 
                    new AuthorizationDecision(true) : new AuthorizationDecision(false);
            })
        );

        return http.build();
    }
}

This ensures API access is controlled dynamically based on the user's assigned role and its permissions.


4️⃣ Deploy & Test

Create a Role for a Tenant

POST /api/tenants/TENANT1/roles/create?roleName=MANAGER

Assign Permissions to Role

POST /api/tenants/TENANT1/roles/MANAGER/permissions
Body: ["CREATE_EVENT", "EDIT_PROJECT"]

Ensure Role Can Access Only Assigned APIs Now, users with MANAGER can only create events and edit projects, but not delete users or modify other tenants.

Would you like UI integration for managing roles and permissions? 🚀

8. UI integration for managing roles and permissions

⚠️ **GitHub.com Fallback** ⚠️