fish_lib/game/repositories/
user_repository.rs1use crate::database::DatabaseInterface;
2use crate::game::errors::repository::GameRepositoryError;
3use crate::models::user::{NewUser, User};
4use crate::models::user_location::{NewUserLocation, UserLocation};
5use crate::schema::{fish_user_locations, fish_users};
6use crate::traits::repository::Repository;
7use chrono::Utc;
8use diesel::prelude::*;
9use std::sync::{Arc, RwLock};
10
11pub trait UserRepositoryInterface: Repository<User> + Send + Sync {
12 fn find_by_external_id(&self, external_id: i64) -> Result<Option<User>, GameRepositoryError>;
13 fn find_unlocked_locations(&self, id: i64) -> Result<Vec<UserLocation>, GameRepositoryError>;
14 fn find_unlocked_location_ids(&self, id: i64) -> Result<Vec<i32>, GameRepositoryError>;
15 fn unlock_location(
16 &self,
17 id: i64,
18 location_id: i32,
19 ) -> Result<UserLocation, GameRepositoryError>;
20}
21
22pub struct UserRepository {
23 db: Arc<RwLock<dyn DatabaseInterface>>,
24}
25
26impl UserRepository {
27 pub fn new(db: Arc<RwLock<dyn DatabaseInterface>>) -> Self {
28 Self { db }
29 }
30}
31
32impl UserRepositoryInterface for UserRepository {
33 fn find_by_external_id(&self, external_id: i64) -> Result<Option<User>, GameRepositoryError> {
34 let mut connection = self.get_connection()?;
35 let user = fish_users::table
36 .filter(fish_users::external_id.eq(external_id))
37 .first::<User>(&mut connection)
38 .optional()?;
39 Ok(user)
40 }
41
42 fn find_unlocked_locations(&self, id: i64) -> Result<Vec<UserLocation>, GameRepositoryError> {
43 let mut connection = self.get_connection()?;
44
45 let locations = fish_user_locations::table
46 .filter(fish_user_locations::user_id.eq(id))
47 .load::<UserLocation>(&mut connection)?;
48
49 Ok(locations)
50 }
51
52 fn find_unlocked_location_ids(&self, id: i64) -> Result<Vec<i32>, GameRepositoryError> {
53 let mut connection = self.get_connection()?;
54
55 let locations = fish_user_locations::table
56 .filter(fish_user_locations::user_id.eq(id))
57 .select(fish_user_locations::location_id)
58 .load::<i32>(&mut connection)?;
59
60 Ok(locations)
61 }
62
63 fn unlock_location(
64 &self,
65 id: i64,
66 location_id: i32,
67 ) -> Result<UserLocation, GameRepositoryError> {
68 let mut connection = self.get_connection()?;
69
70 let user_location = diesel::insert_into(fish_user_locations::table)
71 .values(NewUserLocation {
72 user_id: id,
73 location_id,
74 })
75 .get_result(&mut connection)?;
76 Ok(user_location)
77 }
78}
79
80impl Repository<User> for UserRepository {
81 fn get_db(&self) -> Arc<RwLock<dyn DatabaseInterface>> {
82 self.db.clone()
83 }
84
85 fn create(&self, new_entity: NewUser) -> Result<User, GameRepositoryError> {
86 let mut connection = self.get_connection()?;
87
88 let new_result = diesel::insert_into(fish_users::table)
89 .values(new_entity)
90 .get_result::<User>(&mut connection)?;
91
92 Ok(new_result)
93 }
94
95 fn find(&self, id: i64) -> Result<Option<User>, GameRepositoryError> {
96 let mut connection = self.get_connection()?;
97 let user = fish_users::table
98 .find(id)
99 .first::<User>(&mut connection)
100 .optional()?;
101 Ok(user)
102 }
103
104 fn save(&self, mut entity: User) -> Result<User, GameRepositoryError> {
105 let mut connection = self.get_connection()?;
106 entity.updated_at = Utc::now();
107
108 let updated_user = diesel::update(fish_users::table)
109 .filter(fish_users::id.eq(entity.id))
110 .set(entity)
111 .get_result::<User>(&mut connection)?;
112
113 Ok(updated_user)
114 }
115
116 fn delete(&self, entity: User) -> Result<bool, GameRepositoryError> {
117 let mut connection = self.get_connection()?;
118
119 let deleted_count = diesel::delete(fish_users::table)
120 .filter(fish_users::id.eq(entity.id))
121 .execute(&mut connection)?;
122
123 Ok(deleted_count > 0)
124 }
125}