Skip to content

Commit

Permalink
deploymenents and SecurityConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
felixojiambo committed Oct 20, 2024
1 parent bedad36 commit 3f7e59b
Show file tree
Hide file tree
Showing 15 changed files with 359 additions and 4 deletions.
14 changes: 14 additions & 0 deletions user-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM ubuntu:latest
LABEL authors="OjiamboFelix"

ENTRYPOINT ["top", "-b"]

FROM openjdk:23-jdk-alpine

WORKDIR /app

COPY target/user-service-0.0.1-SNAPSHOT.jar user-service.jar

EXPOSE 8082

ENTRYPOINT ["java", "-jar", "user-service.jar"]
9 changes: 9 additions & 0 deletions user-service/helm/ secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# FinPay/user-service/helm/finpay-user-service/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: finpay-user-service-secrets
type: Opaque
data:
spring.datasource.password: cG9zdGdyZXNwYXNzd29yZA== # Replace with Base64 encoded password
jwt.secret: WW91ckpXVFRlY3JldEtleQ== # Replace with Base64 encoded JWT secret
42 changes: 42 additions & 0 deletions user-service/helm/ values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# FinPay/user-service/helm/finpay-user-service/values.yaml
replicaCount: 2

image:
repository: yourdockerhubusername/finpay-user-service
pullPolicy: IfNotPresent
tag: "0.0.1-SNAPSHOT"

service:
type: ClusterIP
port: 8082

env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: SPRING_DATASOURCE_URL
value: jdbc:postgresql://finpay-db:5432/finpay_user
- name: SPRING_DATASOURCE_USERNAME
value: postgres
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: finpay-user-service-secrets
key: spring.datasource.password
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: finpay-user-service-secrets
key: jwt.secret
- name: JWT_EXPIRATION
value: "86400000"

resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"

ingress:
enabled: false
7 changes: 7 additions & 0 deletions user-service/helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# FinPay/user-service/helm/finpay-user-service/Chart.yaml
apiVersion: v2
name: finpay-user-service
description: User Management Service for FinPay
type: application
version: 0.1.0
appVersion: "1.0"
37 changes: 37 additions & 0 deletions user-service/helm/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# FinPay/user-service/helm/finpay-user-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: finpay-user-service
labels:
app: finpay-user-service
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: finpay-user-service
template:
metadata:
labels:
app: finpay-user-service
spec:
containers:
- name: finpay-user-service
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8082
env:
{{- range .Values.env }}
- name: {{ .name }}
{{- if .valueFrom }}
valueFrom:
secretKeyRef:
name: {{ .valueFrom.secretKeyRef.name }}
key: {{ .valueFrom.secretKeyRef.key }}
{{- else }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
16 changes: 16 additions & 0 deletions user-service/helm/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# FinPay/user-service/helm/finpay-user-service/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: finpay-user-service
labels:
app: finpay-user-service
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: 8082
protocol: TCP
name: http
selector:
app: finpay-user-service
5 changes: 5 additions & 0 deletions user-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.finpay.user_service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {

public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
System.out.println("User Service Application Started");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.finpay.user_service.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;

@Configuration
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/users/register").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.jwtAuthenticationConverter(jwtAuthenticationConverter())
)
);

return http.build();
}

private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthoritiesClaimName("roles"); // Assuming roles are in the 'roles' claim
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");

JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
authenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
return authenticationConverter;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.finpay.user_service.controllers;

import com.finpay.user_service.dtos.RoleAssignmentRequest;
import com.finpay.user_service.dtos.UserRegistrationRequest;
import com.finpay.user_service.dtos.UserResponse;
import com.finpay.user_service.models.Role;
import com.finpay.user_service.models.User;
import com.finpay.user_service.services.UserService;
import org.springframework.http.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;
import java.util.Set;
import java.util.UUID;

@RestController
@RequestMapping("/api/users")
public class UserController {

private final UserService userService;
// Constructor-based injection
public UserController(UserService userService) {
this.userService = userService;

}
@PostMapping("/register")
public ResponseEntity<?> registerUser(@RequestBody UserRegistrationRequest registrationRequest) {
if (userService.existsByEmail(registrationRequest.getEmail())) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body("Error: Email is already in use!");
}

// Assign default role
Set<Role> defaultRoles = Set.of(Role.ROLE_USER);

User user = User.builder()
.id(UUID.randomUUID())
.name(registrationRequest.getName())
.email(registrationRequest.getEmail())
.password(registrationRequest.getPassword())
.roles(defaultRoles)
.build();

User savedUser = userService.save(user);

UserResponse userResponse = new UserResponse(savedUser.getId(), savedUser.getName(), savedUser.getEmail());

return ResponseEntity.status(HttpStatus.CREATED).body(userResponse);
}

@GetMapping("/profile")
public ResponseEntity<?> getUserProfile(Authentication authentication) {
String email = authentication.getName();
Optional<User> userOpt = userService.findByEmail(email);

if (!userOpt.isPresent()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found.");
}

User user = userOpt.get();
UserResponse userResponse = new UserResponse(user.getId(), user.getName(), user.getEmail());

return ResponseEntity.ok(userResponse);
}

// Endpoint to assign roles to a user (Restricted to ADMIN)
@PostMapping("/{id}/roles")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> assignRolesToUser(@PathVariable UUID id, @RequestBody RoleAssignmentRequest roleAssignmentRequest) {
Optional<User> userOpt = userService.findById(id);

if (userOpt.isEmpty()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found.");
}

User user = userOpt.get();
Set<Role> roles = roleAssignmentRequest.getRoles();

userService.assignRoles(user, roles);

return ResponseEntity.ok("Roles assigned successfully.");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.finpay.user_service.dtos;
import com.finpay.user_service.models.Role;
import lombok.Data;

import java.util.Set;
@Data
public class RoleAssignmentRequest {
private Set<Role> roles;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.finpay.user_service.dtos;
import lombok.*;

@Data
public class UserRegistrationRequest {
private String name;
private String email;
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.finpay.user_service.dtos;
import lombok.*;
import java.util.UUID;

@Data
@AllArgsConstructor
public class UserResponse {
private UUID id;
private String name;
private String email;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package com.finpay.user_service.models;

import lombok.Getter;

import java.util.Set;

@Getter
public enum Role {
ROLE_USER(Set.of(Permission.READ_USER)),
ROLE_ADMIN(Set.of(Permission.READ_USER, Permission.WRITE_USER, Permission.DELETE_USER, Permission.READ_INVOICE, Permission.WRITE_INVOICE, Permission.DELETE_INVOICE)),
ROLE_MANAGER(Set.of(Permission.READ_USER, Permission.WRITE_USER, Permission.READ_INVOICE, Permission.WRITE_INVOICE));
ROLE_ADMIN(Set.of(
Permission.READ_USER,
Permission.WRITE_USER,
Permission.DELETE_USER,
Permission.READ_INVOICE,
Permission.WRITE_INVOICE,
Permission.DELETE_INVOICE
)),
ROLE_MANAGER(Set.of(
Permission.READ_USER,
Permission.WRITE_USER,
Permission.READ_INVOICE,
Permission.WRITE_INVOICE
));

private final Set<Permission> permissions;

Expand Down
Loading

0 comments on commit 3f7e59b

Please sign in to comment.