REFINE OAuth2 user handling and update database schema

This commit is contained in:
2025-06-23 23:28:29 +02:00
parent 8d7f74e189
commit c7b3f6bf70
8 changed files with 56 additions and 54 deletions

View File

@@ -1,19 +1,23 @@
import { Menu, X} from 'lucide-react'; import { Menu, X } from 'lucide-react';
import MenuButton from "./buttons/MenuButton.tsx"; import MenuButton from "./buttons/MenuButton.tsx";
import clsx from "clsx"; import clsx from "clsx";
type props = { type props = {
sidebarToggled: boolean, sidebarToggled: boolean;
setSidebarToggled: Function setSidebarToggled: Function;
className?: string; className?: string;
} }
const Topbar = ({sidebarToggled, setSidebarToggled, className}: props) => { const Topbar = ({sidebarToggled, setSidebarToggled, className}: props) => {
return ( return (
<div className={clsx(className)}> <div className={clsx(className, "flex justify-between")}>
<MenuButton onClick={() => setSidebarToggled(!sidebarToggled)}> <MenuButton onClick={() => setSidebarToggled(!sidebarToggled)}>
{sidebarToggled ? <Menu size={24}/> : <X size={24}/>} {sidebarToggled ? <Menu size={24}/> : <X size={24}/>}
</MenuButton> </MenuButton>
<MenuButton className={"w-20 text-gray-600"}>
Login
</MenuButton>
</div> </div>
) )
} }

View File

@@ -6,7 +6,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.Map; import java.util.Map;
@RestController @RestController
@@ -15,7 +14,7 @@ public class AuthController {
@GetMapping("/user") @GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) { public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return Collections.singletonMap("name", principal.getAttribute("name")); return principal.getAttributes();
} }
@GetMapping("/login") @GetMapping("/login")

View File

@@ -29,7 +29,7 @@ public class User {
@Column(name = "role", nullable = false) @Column(name = "role", nullable = false)
private Integer role; // 0: user, 1: admin private Integer role; // 0: user, 1: admin
@Column(name = "created_at", nullable = false) @Column(name = "created_at")
private LocalDateTime createdAt; private LocalDateTime createdAt;
} }

View File

@@ -1,17 +1,15 @@
package com.ddf.vodsystem.security; package com.ddf.vodsystem.security;
import com.ddf.vodsystem.entities.User;
import com.ddf.vodsystem.repositories.UserRepository; import com.ddf.vodsystem.repositories.UserRepository;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Optional;
@Service @Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService { public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository; private final UserRepository userRepository;
@@ -20,25 +18,21 @@ public class CustomOAuth2UserService extends DefaultOAuth2UserService {
} }
@Override @Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) { public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oauthUser = super.loadUser(userRequest); OAuth2User oAuth2User = super.loadUser(userRequest);
String googleId = oauthUser.getAttribute("sub"); // Google's unique user ID // String email = oAuth2User.getAttribute("email");
String email = oauthUser.getAttribute("email"); // String name = oAuth2User.getAttribute("name");
String name = oauthUser.getAttribute("name"); // String googleId = oAuth2User.getAttribute("sub");
//
// userRepository.findByGoogleId(googleId).orElseGet(() -> {
// User user = new User();
// user.setEmail(email);
// user.setName(name);
// user.setGoogleId(googleId);
// return userRepository.save(user);
// });
Optional<User> userOptional = userRepository.findByGoogleId(googleId); return oAuth2User;
User user;
if (userOptional.isEmpty()) {
user = new User();
user.setGoogleId(googleId);
user.setEmail(email);
user.setName(name);
user.setUsername(email.split("@")[0]);
user.setCreatedAt(LocalDateTime.now());
userRepository.save(user);
}
return oauthUser;
} }
} }

View File

@@ -3,10 +3,14 @@ package com.ddf.vodsystem.security;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
@Configuration @Configuration
@EnableWebSecurity
public class SecurityConfig { public class SecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService; private final CustomOAuth2UserService customOAuth2UserService;
@@ -20,19 +24,22 @@ public class SecurityConfig {
http http
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/css/**", "api/v1/**").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.oauth2Login(oauth2 -> oauth2 .oauth2Login(oauth2 -> oauth2
.loginPage("/login")
.userInfoEndpoint(userInfo -> userInfo .userInfoEndpoint(userInfo -> userInfo
.userService(customOAuth2UserService)) .userService(customOAuth2UserService)
)
.logout(logout -> logout )
.logoutSuccessUrl("/") .successHandler(successHandler())
.permitAll()
); );
return http.build(); return http.build();
} }
@Bean
public AuthenticationSuccessHandler successHandler() {
return new SimpleUrlAuthenticationSuccessHandler("/api/v1/auth/user");
}
} }

View File

@@ -13,4 +13,3 @@ spring.sql.init.data-locations=classpath:db/data.sql
spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID} spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET} spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
spring.security.oauth2.client.registration.google.scope=openid,profile,email spring.security.oauth2.client.registration.google.scope=openid,profile,email
spring.security.oauth2.client.registration.google.redirect-uri=http://localhost:8080/login/oauth2/code/google

View File

@@ -1,15 +1,15 @@
INSERT INTO users (id, google_id, username, email, name) INSERT INTO users ( google_id, username, email, name)
VALUES VALUES
(1, 'google-uid-001', 'alice', 'alice@example.com', 'Alice Example'), ('google-uid-001', 'alice', 'alice@example.com', 'Alice Example'),
(2, 'google-uid-002', 'bob', 'bob@example.com', 'Bob Example'), ( 'google-uid-002', 'bob', 'bob@example.com', 'Bob Example'),
(3, 'google-uid-003', 'carol', 'carol@example.com', 'Carol Example'), ('google-uid-003', 'carol', 'carol@example.com', 'Carol Example'),
(4, 'google-uid-004', 'wizard42', 'gandalf@middle.earth', 'Gandalf the Grey'), ( 'google-uid-004', 'wizard42', 'gandalf@middle.earth', 'Gandalf the Grey'),
(5, 'google-uid-005', 'catnap', 'whiskers@meowmail.com', 'Sir Whiskers McFluff'), ( 'google-uid-005', 'catnap', 'whiskers@meowmail.com', 'Sir Whiskers McFluff'),
(6, 'google-uid-006', 'robotron', 'bender@futurama.tv', 'Bender Rodriguez'), ( 'google-uid-006', 'robotron', 'bender@futurama.tv', 'Bender Rodriguez'),
(7, 'google-uid-007', 'unicorn', 'sparkle@rainbow.com', 'Princess Sparklehoof'), ('google-uid-007', 'unicorn', 'sparkle@rainbow.com', 'Princess Sparklehoof'),
(8, 'google-uid-008', 'pirate', 'blackbeard@seas.com', 'Edward Teach'), ( 'google-uid-008', 'pirate', 'blackbeard@seas.com', 'Edward Teach'),
(9, 'google-uid-009', 'detective', 'holmes@bakerstreet.uk', 'Sherlock Holmes'), ( 'google-uid-009', 'detective', 'holmes@bakerstreet.uk', 'Sherlock Holmes'),
(10, 'google-uid-010', 'timey', 'docbrown@delorean.net', 'Dr. Emmett Brown'); ( 'google-uid-010', 'timey', 'docbrown@delorean.net', 'Dr. Emmett Brown');
INSERT INTO clips (id, user_id, title, description, width, height, fps, duration, file_size, video_path) INSERT INTO clips (id, user_id, title, description, width, height, fps, duration, file_size, video_path)
VALUES VALUES

View File

@@ -2,18 +2,17 @@ DROP TABLE IF EXISTS clips;
DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS users;
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id BIGINT PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
google_id VARCHAR(64), google_id VARCHAR(64),
username VARCHAR(50) NOT NULL UNIQUE, username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
role INTEGER DEFAULT 0, role INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
); );
CREATE TABLE IF NOT EXISTS clips ( CREATE TABLE IF NOT EXISTS clips (
id BIGINT PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL, user_id BIGINT NOT NULL,
title VARCHAR(255) NOT NULL, title VARCHAR(255) NOT NULL,
description TEXT, description TEXT,