Newer
Older
tampopo-server / src / main / java / org / ntlab / tampoposerver / resources / UsersResource.java
package org.ntlab.tampoposerver.resources;

import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.ntlab.tampoposerver.models.FriendPair;
import org.ntlab.tampoposerver.repositories.UserRepository;
import org.ntlab.tampoposerver.models.User;
import org.ntlab.tampoposerver.services.FriendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static io.micrometer.common.util.StringUtils.isBlank;
/*
//6/10報告:全部できた(friendまで)、UserRepositoryとの連携ができていない(updateあります?)、responseがない
//6/17報告:すべてのユーザーの情報を持ってくるところ、フレンドペアの自分じゃない方のuidを返すところ、フレンドペアの削除はもらったものを連携できていない

マスタからこのブランチへと取り込む
ブランチ checkout
masterからブランチへ引き込む
Git → Merge → git merge origin/master

別のクラスへのアクセス方法
コンストラクタを作る
import class
コンストラクタの上に@Autowired これを入れるとspring bootが管理しているuserRepositoryのインスタンスを渡してくれる
Repositoru側の説明 Repositoryをつけるとspring bootがインスタンスを1個だけ勝手に作ってくれる シングルトン
変数名は先頭小文字

未コミットの編集→スタッシュで書き換えてしまったコードを退避させることができる

ポストマンでテスト
1.
*/

@Path("/users")
@Component
public class UsersResource {


    private final UserRepository userRepository;
    private final FriendService  friendService;

    @Autowired
    public UsersResource(UserRepository userRepository,
                         FriendService  friendService) { //インスタンスを作るときに呼び出されるメソッドであるコンストラクタを書く
        this.userRepository = userRepository;
        this.friendService  = friendService;
    }

    //@Path("/{uid}/..")などパスを指定する
    //アカウントの基本情報
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    /*関数の名前を適切なものに変更する
    関数の引数に@PathParam("uid") String uidのような形でパラメーターを定義しておく
    Queryの場合は@QueryParam("filter") String filter
    repositoryのメソッド名:add, get, delete
    本来の流れはインターフェースだけ決めておく メソッド名と引数名*/
    public Response getUsers() {
        List<User> users = userRepository.getAllUsers();
        if (users.isEmpty()) {
            return Response.noContent().build();
        }
        return Response.ok(users).build();
    }


    //新規アカウントを作る
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response createUser(@FormParam("user-id") String userId, @FormParam("password") String password) {

        if (isBlank(userId) || isBlank(password)) {
            throw new WebApplicationException(
                    Response.status(Response.Status.BAD_REQUEST)
                            .entity("ユーザーIDおよびパスワードを入力してください")
                            .build());
        }

        //ユーザーがいるか調べる
        User existingUser = userRepository.getUser(userId);
        if (existingUser != null) {
            return Response.status(Response.Status.CONFLICT)
                    .entity("すでにユーザーが存在しています")
                    .build();
        }

        User newUser = userRepository.addUser(userId, password);

        //6/12ここはswaggerではなくコードを仕様にすると決定しました。
        //return Response.ok(user.login(), MediaType.APPLICATION_JSON).build();
        return Response.status(Response.Status.CREATED)
                .entity(newUser)   // 仮に JSON を返したい場合
                .build();

    }

    //単一アカウントの情報を返す
    @GET
    @Path("/{user-id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response getUser(@PathParam("user-id") String userId) {
        //取得
        User user = userRepository.getUser(userId);
        //存在の確認
        if (user == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return Response.ok(user, MediaType.APPLICATION_JSON).build();
    }

    //ユーザの削除 ok
    @DELETE
    //deleteはquery parameter
    @Path("/{user-id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response deleteUser(@PathParam("user-id") String userId, @QueryParam("token") String token) {
        //取得
        User user = userRepository.getUser(userId);
        //存在チェック
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("404 IDが存在しません")
                            .build()
            );
        }

        if (!token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("401 認証失敗")
                            .build()
            );
        }

        //削除処理
        userRepository.deleteUser(userId);
        return Response.noContent().build();
    }


    //ログイン
    @POST
    @Path("/{user-id}/login")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response login(@PathParam("user-id") String userId, @FormParam("password") String password) {



        if (userId == null || userId.isBlank()) {
            throw new WebApplicationException(
                    Response.status(Response.Status.BAD_REQUEST)
                            .entity("user-id は必須です")
                            .build());
        }

        if (password == null || password.isBlank()) {
            throw new WebApplicationException(
                    Response.status(Response.Status.BAD_REQUEST)
                            .entity("password は必須です")
                            .build());
        }

        //存在チェック
        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("IDが存在しません")
                            .build()
            );
        }

        //パスワードチェック 適切なステータスはなんですか?
        if (!password.equals(user.getPassword())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.UNAUTHORIZED)
                            .entity("パスワードが間違っています")
                            .build()
            );
        }

        //トークン発行
        String token = user.login();

        return Response.ok(token).build();

    }

    //アカウントのニックネームの取得 ok
    @GET
    @Path("/{user-id}/name")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getName(@PathParam("user-id") String userId) {
        //取得
        User user = userRepository.getUser(userId);
        //存在チェック
        if (user == null) {
            throw new WebApplicationException(
                    Response.Status.NOT_FOUND
            );
        }

        return Response.ok(user.getName(), MediaType.APPLICATION_JSON).build();
    }

    //ニックネームの変更
    @PUT
    @Path("/{user-id}/name")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response updateName(@PathParam("user-id") String userId, @FormParam("new-name") String newName, @FormParam("token") String token) {

        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }

        //ニックネームアップデート
        user.setName(newName);
        return Response.ok(user.getName(), MediaType.APPLICATION_JSON).build();

    }

    //単一アカウントのパスワードの取得 ok
    @GET
    @Path("/{user-id}/password")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPassword(@PathParam("user-id") String userId, @QueryParam("token") String token) {
        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }

        return Response.ok(user.getPassword(), MediaType.APPLICATION_JSON).build();
    }

    //指定されたIDのパスワードを変更する
    @PUT
    @Path("/{user-id}/password")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response updatePassword(@PathParam("user-id") String userId, @FormParam("new-password") String newPassword, @FormParam("token") String token) {

        if (newPassword == null || newPassword.isBlank()) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }

        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }


        //パスワードのアップデート
        user.setPassword(newPassword);
        return Response.ok().build();

    }


    //単一アカウントのemailの取得
    @GET
    @Path("/{user-id}/email")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getEmail(@PathParam("user-id") String userId, @QueryParam("token") String token) {

        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }
        return Response.ok(user.getEmail(), MediaType.APPLICATION_JSON).build();
    }

    //指定されたIDのemailを変更する
    @PUT
    @Path("/{user-id}/email")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response updateEmail(@PathParam("user-id") String userId, @FormParam("new-email") String newEmail, @FormParam("token") String token) {

        if (newEmail == null || newEmail.isBlank()) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }


        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }

        if (!newEmail.equals(user.getEmail())) {
            throw new WebApplicationException(Response.Status.CONFLICT);
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }



        //emailアップデート
        user.setEmail(newEmail);
        return Response.ok(user.getEmail(), MediaType.APPLICATION_JSON).build();

    }

    //指定されたIDのアイコンを返す
    @GET
    @Path("/{user-id}/icon")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getIcon(@PathParam("user-id") String userId) {
        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return Response.ok(user.getIcon(), MediaType.APPLICATION_JSON).build();
    }

    //アイコンを変更する
    @PUT
    @Path("/{user-id}/icon")
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public String updateIcon(@PathParam("user-id") String userId, @FormParam("new-icon") String newIcon, @FormParam("token") String token) {

        if ( newIcon == null || newIcon.isBlank() ) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }

        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }

        //アイコンを変更する
        user.setIcon(newIcon);
        return Response.ok(user.getIcon(), MediaType.APPLICATION_JSON).build().toString();

    }

    //フレンド相手の情報の取得
    @GET
    @Path("/{user-id}/friends")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getFriends(@PathParam("user-id") String userId, @QueryParam("token") String token) {
        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }
        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }
        //pairIdを取ってきて自分じゃない方のuserIdを渡す
        List<String> friendIds = friendService.getFriendIds(token, userId);
        if (friendIds == null) {                  // 認証失敗 or ユーザ無し
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗またはユーザ不一致")
                            .build());
        }

        return Response
                .ok()
                .build();
    }


    //自分のペアのpid一覧(JSON)の取得
    @GET
    @Path("/{user-id}/friends/{pair-id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPairId(@PathParam("user-id") String userId, @QueryParam("token") String token, @PathParam("pair-id") String pairId) {

        if (pairId == null || pairId.isBlank()) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }

        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new WebApplicationException(
                    Response.status(Response.Status.NOT_FOUND)
                            .entity("ユーザーが存在しません")
                            .build()
            );
        }

        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }

        ArrayList<FriendPair> pairIds = user.getFriendPairs();

        // JSON で返す
        return Response.ok(pairIds).build();
    }


    //ペアの削除 
    @DELETE
    @Path("/{user-id}/friends/{pair-id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response deleteFriends(@PathParam("user-id") String userId, @PathParam("pair-id") Integer pairId, @QueryParam("token") String token) {

        if (pairId == null || pairId <= 0) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
        User user = userRepository.getUser(userId);
        if (user == null) {
            throw new NotFoundException("IDが存在しません");
        }

        //トークン認証
        if (token == null || !token.equals(user.getToken())) {
            throw new WebApplicationException(
                    Response.status(Response.Status.FORBIDDEN)
                            .entity("認証失敗")
                            .build()
            );
        }


        boolean removed = friendService.removeFriendPair(token, pairId);
        if(!removed) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }

        return Response.noContent().build();
    }
}