Fix login 401, admin permission, video links serialization, and admin UI styling

- Fix UserInfo boolean field naming (isAdmin → admin) for proper Jackson/MyBatis mapping
- Configure Google OAuth audience with actual client ID to fix token verification
- Parse CLOB fields and convert Oracle TIMESTAMP in restaurant video links API
- Add explicit bg-white/text-gray-900 to admin page inputs, selects, and table headers
- Add keyPrefix to RestaurantList to avoid duplicate React keys across desktop/mobile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
joungmin
2026-03-09 21:41:57 +09:00
parent c16add08c3
commit 16bd83c570
9 changed files with 51 additions and 37 deletions

View File

@@ -16,7 +16,7 @@ public class UserInfo {
private String nickname;
private String avatarUrl;
@JsonProperty("is_admin")
private boolean isAdmin;
private boolean admin;
private String provider;
private String providerId;
private String createdAt;

View File

@@ -6,6 +6,7 @@ import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.tasteby.domain.UserInfo;
import com.tasteby.security.JwtTokenProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
@@ -20,12 +21,13 @@ public class AuthService {
private final JwtTokenProvider jwtProvider;
private final GoogleIdTokenVerifier verifier;
public AuthService(UserService userService, JwtTokenProvider jwtProvider) {
public AuthService(UserService userService, JwtTokenProvider jwtProvider,
@Value("${app.google.client-id}") String googleClientId) {
this.userService = userService;
this.jwtProvider = jwtProvider;
this.verifier = new GoogleIdTokenVerifier.Builder(
new NetHttpTransport(), GsonFactory.getDefaultInstance())
.setAudience(Collections.emptyList()) // Accept any audience
.setAudience(Collections.singletonList(googleClientId))
.build();
}

View File

@@ -35,7 +35,13 @@ public class RestaurantService {
public List<Map<String, Object>> findVideoLinks(String restaurantId) {
var rows = mapper.findVideoLinks(restaurantId);
return rows.stream().map(JsonUtil::lowerKeys).toList();
return rows.stream().map(row -> {
var m = JsonUtil.lowerKeys(row);
m.put("foods_mentioned", JsonUtil.parseStringList(m.get("foods_mentioned")));
m.put("evaluation", JsonUtil.parseMap(m.get("evaluation")));
m.put("guests", JsonUtil.parseStringList(m.get("guests")));
return m;
}).toList();
}
public void update(String id, Map<String, Object> fields) {

View File

@@ -54,6 +54,7 @@ app:
google:
maps-api-key: ${GOOGLE_MAPS_API_KEY}
youtube-api-key: ${YOUTUBE_DATA_API_KEY}
client-id: ${GOOGLE_CLIENT_ID:635551099330-2l003d3ernjmkqavd4f6s78r8r405iml.apps.googleusercontent.com}
cache:
ttl-seconds: 600

View File

@@ -60,7 +60,8 @@
</select>
<select id="findVideoLinks" resultType="map">
SELECT v.video_id, v.title, v.url, v.published_at,
SELECT v.video_id, v.title, v.url,
TO_CHAR(v.published_at, 'YYYY-MM-DD"T"HH24:MI:SS') AS published_at,
vr.foods_mentioned, vr.evaluation, vr.guests,
c.channel_name, c.channel_id
FROM video_restaurants vr

View File

@@ -7,7 +7,7 @@
<result property="email" column="email"/>
<result property="nickname" column="nickname"/>
<result property="avatarUrl" column="avatar_url"/>
<result property="isAdmin" column="is_admin" javaType="boolean"/>
<result property="admin" column="is_admin" javaType="boolean"/>
<result property="provider" column="provider"/>
<result property="createdAt" column="created_at"/>
<result property="favoriteCount" column="favorite_count"/>