Merge pull request #8 from sBubshait/feature/post-comments
Comments and Replies to Comments in Backend
This commit is contained in:
commit
6ebf8f4f2d
@ -1,11 +1,9 @@
|
||||
package online.wesal.wesal.config;
|
||||
|
||||
import online.wesal.wesal.service.UserDetailsServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
@ -24,9 +22,6 @@ import java.util.Arrays;
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsServiceImpl userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
@ -35,13 +30,6 @@ public class SecurityConfig {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userDetailsService);
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
@ -71,7 +59,6 @@ public class SecurityConfig {
|
||||
.requestMatchers("/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.authenticationProvider(authenticationProvider())
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
package online.wesal.wesal.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import online.wesal.wesal.dto.ApiResponse;
|
||||
import online.wesal.wesal.dto.CommentCreateRequestDTO;
|
||||
import online.wesal.wesal.dto.CommentResponseDTO;
|
||||
|
||||
import java.util.List;
|
||||
import online.wesal.wesal.service.CommentService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/posts/comments")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Tag(name = "Comments", description = "Comment management endpoints")
|
||||
public class CommentController {
|
||||
|
||||
@Autowired
|
||||
private CommentService commentService;
|
||||
|
||||
@PostMapping(value = "/create", consumes = "application/json", produces = "application/json")
|
||||
@Operation(summary = "Create comment", description = "Create a new comment or reply to an existing comment with 3-level nesting")
|
||||
public ResponseEntity<ApiResponse<CommentResponseDTO>> createComment(
|
||||
@Valid @RequestBody CommentCreateRequestDTO request,
|
||||
BindingResult bindingResult,
|
||||
Authentication authentication) {
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
String errorMessage = bindingResult.getFieldErrors().stream()
|
||||
.map(error -> {
|
||||
String field = error.getField();
|
||||
if ("postId".equals(field)) return "Valid post ID is required";
|
||||
if ("body".equals(field)) return "Comment body is required and cannot exceed 1000 characters";
|
||||
return error.getDefaultMessage();
|
||||
})
|
||||
.findFirst()
|
||||
.orElse("Invalid input");
|
||||
return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
|
||||
}
|
||||
|
||||
try {
|
||||
CommentResponseDTO response = commentService.createComment(
|
||||
request.getPostId(),
|
||||
request.getBody(),
|
||||
request.getReplyComment()
|
||||
);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
} catch (RuntimeException e) {
|
||||
String message;
|
||||
if (e.getMessage().contains("Post not found")) {
|
||||
message = "Post not found";
|
||||
} else if (e.getMessage().contains("Parent comment not found")) {
|
||||
message = "Comment you're replying to not found";
|
||||
} else if (e.getMessage().contains("User not found") || e.getMessage().contains("creator not found")) {
|
||||
message = "Authentication error. Please log in again.";
|
||||
} else {
|
||||
message = "Something went wrong.. We're sorry but try again later";
|
||||
}
|
||||
return ResponseEntity.badRequest().body(ApiResponse.error(message));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "Get comments for post", description = "Get all comments for a specific post in hierarchical structure with nested replies")
|
||||
public ResponseEntity<ApiResponse<List<CommentResponseDTO>>> getCommentsByPostId(
|
||||
@RequestParam Long postId,
|
||||
Authentication authentication) {
|
||||
|
||||
try {
|
||||
if (postId == null || postId <= 0) {
|
||||
return ResponseEntity.badRequest().body(ApiResponse.error("Valid post ID is required"));
|
||||
}
|
||||
|
||||
List<CommentResponseDTO> response = commentService.getCommentsByPostId(postId);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package online.wesal.wesal.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class CommentCreateRequestDTO {
|
||||
|
||||
@NotNull(message = "Post ID is required")
|
||||
private Long postId;
|
||||
|
||||
@NotBlank(message = "Comment body is required")
|
||||
@Size(max = 1000, message = "Comment body cannot exceed 1000 characters")
|
||||
private String body;
|
||||
|
||||
private Long replyComment;
|
||||
|
||||
public CommentCreateRequestDTO() {}
|
||||
|
||||
public CommentCreateRequestDTO(Long postId, String body) {
|
||||
this.postId = postId;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public CommentCreateRequestDTO(Long postId, String body, Long replyComment) {
|
||||
this.postId = postId;
|
||||
this.body = body;
|
||||
this.replyComment = replyComment;
|
||||
}
|
||||
|
||||
public Long getPostId() {
|
||||
return postId;
|
||||
}
|
||||
|
||||
public void setPostId(Long postId) {
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public Long getReplyComment() {
|
||||
return replyComment;
|
||||
}
|
||||
|
||||
public void setReplyComment(Long replyComment) {
|
||||
this.replyComment = replyComment;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package online.wesal.wesal.dto;
|
||||
|
||||
import online.wesal.wesal.entity.Comment;
|
||||
import online.wesal.wesal.entity.User;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CommentResponseDTO {
|
||||
|
||||
private String id;
|
||||
private String postId;
|
||||
private CreatorDTO creator;
|
||||
private String body;
|
||||
private LocalDateTime creationDate;
|
||||
private String replyComment;
|
||||
private String displayReplyComment;
|
||||
private CreatorDTO replyUser;
|
||||
private Integer level;
|
||||
private List<CommentResponseDTO> replies;
|
||||
|
||||
public CommentResponseDTO() {}
|
||||
|
||||
public CommentResponseDTO(Comment comment, User creator, User replyUser) {
|
||||
this.id = String.valueOf(comment.getId());
|
||||
this.postId = String.valueOf(comment.getPostId());
|
||||
this.creator = new CreatorDTO(creator);
|
||||
this.body = comment.getBody();
|
||||
this.creationDate = comment.getCreationDate();
|
||||
this.replyComment = comment.getReplyComment() != null ? String.valueOf(comment.getReplyComment()) : null;
|
||||
this.displayReplyComment = comment.getDisplayReplyComment() != null ? String.valueOf(comment.getDisplayReplyComment()) : null;
|
||||
this.replyUser = replyUser != null ? new CreatorDTO(replyUser) : null;
|
||||
this.level = comment.getLevel();
|
||||
this.replies = new ArrayList<>();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPostId() {
|
||||
return postId;
|
||||
}
|
||||
|
||||
public void setPostId(String postId) {
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
public CreatorDTO getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
public void setCreator(CreatorDTO creator) {
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(LocalDateTime creationDate) {
|
||||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public String getReplyComment() {
|
||||
return replyComment;
|
||||
}
|
||||
|
||||
public void setReplyComment(String replyComment) {
|
||||
this.replyComment = replyComment;
|
||||
}
|
||||
|
||||
public String getDisplayReplyComment() {
|
||||
return displayReplyComment;
|
||||
}
|
||||
|
||||
public void setDisplayReplyComment(String displayReplyComment) {
|
||||
this.displayReplyComment = displayReplyComment;
|
||||
}
|
||||
|
||||
public CreatorDTO getReplyUser() {
|
||||
return replyUser;
|
||||
}
|
||||
|
||||
public void setReplyUser(CreatorDTO replyUser) {
|
||||
this.replyUser = replyUser;
|
||||
}
|
||||
|
||||
public Integer getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(Integer level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public List<CommentResponseDTO> getReplies() {
|
||||
return replies;
|
||||
}
|
||||
|
||||
public void setReplies(List<CommentResponseDTO> replies) {
|
||||
this.replies = replies;
|
||||
}
|
||||
}
|
||||
130
backend/src/main/java/online/wesal/wesal/entity/Comment.java
Normal file
130
backend/src/main/java/online/wesal/wesal/entity/Comment.java
Normal file
@ -0,0 +1,130 @@
|
||||
package online.wesal.wesal.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "comments")
|
||||
public class Comment {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, name = "post_id")
|
||||
private Long postId;
|
||||
|
||||
@Column(nullable = false, name = "creator_id")
|
||||
private Long creatorId;
|
||||
|
||||
@Column(nullable = false, length = 1000)
|
||||
@NotBlank
|
||||
private String body;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime creationDate = LocalDateTime.now();
|
||||
|
||||
@Column(name = "reply_comment")
|
||||
private Long replyComment;
|
||||
|
||||
@Column(name = "display_reply_comment")
|
||||
private Long displayReplyComment;
|
||||
|
||||
@Column(name = "reply_user")
|
||||
private Long replyUser;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer level = 1;
|
||||
|
||||
public Comment() {}
|
||||
|
||||
public Comment(Long postId, Long creatorId, String body) {
|
||||
this.postId = postId;
|
||||
this.creatorId = creatorId;
|
||||
this.body = body;
|
||||
this.level = 1;
|
||||
}
|
||||
|
||||
public Comment(Long postId, Long creatorId, String body, Long replyComment, Long displayReplyComment, Long replyUser, Integer level) {
|
||||
this.postId = postId;
|
||||
this.creatorId = creatorId;
|
||||
this.body = body;
|
||||
this.replyComment = replyComment;
|
||||
this.displayReplyComment = displayReplyComment;
|
||||
this.replyUser = replyUser;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getPostId() {
|
||||
return postId;
|
||||
}
|
||||
|
||||
public void setPostId(Long postId) {
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
public Long getCreatorId() {
|
||||
return creatorId;
|
||||
}
|
||||
|
||||
public void setCreatorId(Long creatorId) {
|
||||
this.creatorId = creatorId;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(LocalDateTime creationDate) {
|
||||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public Long getReplyComment() {
|
||||
return replyComment;
|
||||
}
|
||||
|
||||
public void setReplyComment(Long replyComment) {
|
||||
this.replyComment = replyComment;
|
||||
}
|
||||
|
||||
public Long getDisplayReplyComment() {
|
||||
return displayReplyComment;
|
||||
}
|
||||
|
||||
public void setDisplayReplyComment(Long displayReplyComment) {
|
||||
this.displayReplyComment = displayReplyComment;
|
||||
}
|
||||
|
||||
public Long getReplyUser() {
|
||||
return replyUser;
|
||||
}
|
||||
|
||||
public void setReplyUser(Long replyUser) {
|
||||
this.replyUser = replyUser;
|
||||
}
|
||||
|
||||
public Integer getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(Integer level) {
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package online.wesal.wesal.repository;
|
||||
|
||||
import online.wesal.wesal.entity.Comment;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface CommentRepository extends JpaRepository<Comment, Long> {
|
||||
|
||||
List<Comment> findByPostIdOrderByCreationDateDesc(Long postId);
|
||||
|
||||
@Query("SELECT c FROM Comment c WHERE c.postId = :postId ORDER BY c.creationDate ASC")
|
||||
List<Comment> findByPostIdOrderByCreationDateAsc(@Param("postId") Long postId);
|
||||
|
||||
Optional<Comment> findByIdAndPostId(Long id, Long postId);
|
||||
|
||||
long countByPostId(Long postId);
|
||||
|
||||
@Query("SELECT c FROM Comment c WHERE c.replyComment = :replyComment ORDER BY c.creationDate ASC")
|
||||
List<Comment> findRepliesByReplyComment(@Param("replyComment") Long replyComment);
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package online.wesal.wesal.service;
|
||||
|
||||
import online.wesal.wesal.dto.CommentResponseDTO;
|
||||
import online.wesal.wesal.entity.Comment;
|
||||
import online.wesal.wesal.entity.Post;
|
||||
import online.wesal.wesal.entity.User;
|
||||
import online.wesal.wesal.repository.CommentRepository;
|
||||
import online.wesal.wesal.repository.PostRepository;
|
||||
import online.wesal.wesal.repository.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class CommentService {
|
||||
|
||||
@Autowired
|
||||
private CommentRepository commentRepository;
|
||||
|
||||
@Autowired
|
||||
private PostRepository postRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Transactional
|
||||
public CommentResponseDTO createComment(Long postId, String body, Long replyComment) {
|
||||
User currentUser = userService.getCurrentUser();
|
||||
|
||||
Post post = postRepository.findById(postId)
|
||||
.orElseThrow(() -> new RuntimeException("Post not found"));
|
||||
|
||||
Comment comment;
|
||||
User replyUser = null;
|
||||
|
||||
if (replyComment == null) {
|
||||
comment = new Comment(postId, currentUser.getId(), body);
|
||||
} else {
|
||||
Comment parentComment = commentRepository.findByIdAndPostId(replyComment, postId)
|
||||
.orElseThrow(() -> new RuntimeException("Parent comment not found"));
|
||||
|
||||
replyUser = userRepository.findById(parentComment.getCreatorId())
|
||||
.orElseThrow(() -> new RuntimeException("Parent comment creator not found"));
|
||||
|
||||
Integer newLevel;
|
||||
Long displayReplyComment;
|
||||
|
||||
if (parentComment.getLevel() >= 3) {
|
||||
newLevel = 3;
|
||||
Comment rootComment = findRootCommentForLevel3(parentComment);
|
||||
displayReplyComment = rootComment.getId();
|
||||
} else {
|
||||
newLevel = parentComment.getLevel() + 1;
|
||||
displayReplyComment = replyComment;
|
||||
}
|
||||
|
||||
comment = new Comment(postId, currentUser.getId(), body, replyComment, displayReplyComment, replyUser.getId(), newLevel);
|
||||
}
|
||||
|
||||
comment = commentRepository.save(comment);
|
||||
|
||||
post.setComments(post.getComments() + 1);
|
||||
postRepository.save(post);
|
||||
|
||||
return new CommentResponseDTO(comment, currentUser, replyUser);
|
||||
}
|
||||
|
||||
private Comment findRootCommentForLevel3(Comment comment) {
|
||||
if (comment.getLevel() <= 2) {
|
||||
return comment;
|
||||
}
|
||||
|
||||
if (comment.getReplyComment() != null) {
|
||||
Comment parentComment = commentRepository.findById(comment.getReplyComment())
|
||||
.orElse(comment);
|
||||
return findRootCommentForLevel3(parentComment);
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
public List<CommentResponseDTO> getCommentsByPostId(Long postId) {
|
||||
List<Comment> comments = commentRepository.findByPostIdOrderByCreationDateAsc(postId);
|
||||
|
||||
List<Long> creatorIds = comments.stream()
|
||||
.map(Comment::getCreatorId)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Long> replyUserIds = comments.stream()
|
||||
.map(Comment::getReplyUser)
|
||||
.filter(id -> id != null)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
creatorIds.addAll(replyUserIds);
|
||||
|
||||
Map<Long, User> users = userRepository.findAllById(creatorIds.stream().distinct().collect(Collectors.toList())).stream()
|
||||
.collect(Collectors.toMap(User::getId, user -> user));
|
||||
|
||||
Map<Long, CommentResponseDTO> commentMap = comments.stream()
|
||||
.collect(Collectors.toMap(
|
||||
Comment::getId,
|
||||
comment -> new CommentResponseDTO(comment,
|
||||
users.get(comment.getCreatorId()),
|
||||
comment.getReplyUser() != null ? users.get(comment.getReplyUser()) : null)
|
||||
));
|
||||
|
||||
List<CommentResponseDTO> rootComments = new ArrayList<>();
|
||||
|
||||
for (Comment comment : comments) {
|
||||
CommentResponseDTO dto = commentMap.get(comment.getId());
|
||||
|
||||
if (comment.getDisplayReplyComment() == null) {
|
||||
rootComments.add(dto);
|
||||
} else {
|
||||
CommentResponseDTO parent = commentMap.get(comment.getDisplayReplyComment());
|
||||
if (parent != null) {
|
||||
parent.getReplies().add(dto);
|
||||
} else {
|
||||
rootComments.add(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rootComments;
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@ import 'services/notification_service.dart';
|
||||
import 'services/auth_service.dart';
|
||||
import 'services/user_service.dart';
|
||||
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||
@ -21,6 +23,7 @@ class MyApp extends StatelessWidget {
|
||||
title: 'Wesal',
|
||||
theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Roboto'),
|
||||
home: SplashScreen(),
|
||||
navigatorKey: navigatorKey,
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../constants/api_constants.dart';
|
||||
import '../main.dart';
|
||||
|
||||
class AuthService {
|
||||
static const FlutterSecureStorage _storage = FlutterSecureStorage();
|
||||
@ -87,4 +89,13 @@ class AuthService {
|
||||
static Future<void> clearUserData() async {
|
||||
await _storage.delete(key: _userDataKey);
|
||||
}
|
||||
|
||||
static Future<void> handleAuthenticationError() async {
|
||||
await logout();
|
||||
|
||||
final context = navigatorKey.currentContext;
|
||||
if (context != null && context.mounted) {
|
||||
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
import '../constants/api_constants.dart';
|
||||
import '../models/invitation_models.dart';
|
||||
import 'http_service.dart';
|
||||
import 'auth_service.dart';
|
||||
|
||||
class InvitationsService {
|
||||
static Future<Map<String, dynamic>> getAllInvitations() async {
|
||||
@ -23,16 +24,12 @@ class InvitationsService {
|
||||
invitationsResponse.message ?? 'Failed to fetch invitations',
|
||||
};
|
||||
}
|
||||
} else if (response.statusCode == 401) {
|
||||
} else if (response.statusCode == 401 || response.statusCode == 403) {
|
||||
await AuthService.handleAuthenticationError();
|
||||
return {
|
||||
'success': false,
|
||||
'message': 'Session expired. Please login again.',
|
||||
};
|
||||
} else if (response.statusCode == 403) {
|
||||
return {
|
||||
'success': false,
|
||||
'message': 'Access denied. Invalid credentials.',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
'success': false,
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import 'dart:convert';
|
||||
import '../models/post_models.dart';
|
||||
import 'http_service.dart';
|
||||
import 'auth_service.dart';
|
||||
|
||||
class PostService {
|
||||
static Future<Map<String, dynamic>> getAllPosts() async {
|
||||
try {
|
||||
final response = await HttpService.get('/posts/all');
|
||||
|
||||
final responseData = jsonDecode(response.body);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = jsonDecode(response.body);
|
||||
return {
|
||||
'success': responseData['status'] ?? false,
|
||||
'message': responseData['message'] ?? '',
|
||||
@ -19,12 +19,28 @@ class PostService {
|
||||
.toList() ??
|
||||
[],
|
||||
};
|
||||
} else {
|
||||
} else if (response.statusCode == 401 || response.statusCode == 403) {
|
||||
await AuthService.handleAuthenticationError();
|
||||
return {
|
||||
'success': false,
|
||||
'message': responseData['message'] ?? 'Failed to fetch posts',
|
||||
'message': 'Session expired. Please login again.',
|
||||
'posts': <Post>[],
|
||||
};
|
||||
} else {
|
||||
try {
|
||||
final responseData = jsonDecode(response.body);
|
||||
return {
|
||||
'success': false,
|
||||
'message': responseData['message'] ?? 'Failed to fetch posts',
|
||||
'posts': <Post>[],
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
'success': false,
|
||||
'message': 'Server error (${response.statusCode})',
|
||||
'posts': <Post>[],
|
||||
};
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error fetching posts: $e');
|
||||
|
||||
@ -21,16 +21,12 @@ class UserService {
|
||||
final data = jsonDecode(response.body);
|
||||
await AuthService.saveUserData(data);
|
||||
return {'success': true, 'data': data};
|
||||
} else if (response.statusCode == 401) {
|
||||
} else if (response.statusCode == 401 || response.statusCode == 403) {
|
||||
await AuthService.handleAuthenticationError();
|
||||
return {
|
||||
'success': false,
|
||||
'message': 'Session expired. Please login again.',
|
||||
};
|
||||
} else if (response.statusCode == 403) {
|
||||
return {
|
||||
'success': false,
|
||||
'message': 'Access denied. Invalid credentials.',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
'success': false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user