@@ -21,6 +21,9 @@ type UserRepository interface {
2121 GetUserByGithubId (ctx context.Context , tx * sqlx.Tx , githubId int ) (User , error )
2222 CreateUser (ctx context.Context , tx * sqlx.Tx , userInfo CreateUserRequestBody ) (User , error )
2323 UpdateUserEmail (ctx context.Context , tx * sqlx.Tx , userId int , email string ) error
24+ MarkUserAsDeleted (ctx context.Context , tx * sqlx.Tx , userID int , deletedAt time.Time ) (User , error )
25+ AccountScheduledForDelete (ctx context.Context , tx * sqlx.Tx , userID int ) error
26+ DeleteUser (tx * sqlx.Tx ) error
2427}
2528
2629func NewUserRepository (db * sqlx.DB ) UserRepository {
@@ -120,6 +123,8 @@ func (ur *userRepository) CreateUser(ctx context.Context, tx *sqlx.Tx, userInfo
120123 userInfo .GithubUsername ,
121124 userInfo .Email ,
122125 userInfo .AvatarUrl ,
126+ time .Now (),
127+ time .Now (),
123128 ).Scan (
124129 & user .Id ,
125130 & user .GithubId ,
@@ -156,3 +161,76 @@ func (ur *userRepository) UpdateUserEmail(ctx context.Context, tx *sqlx.Tx, user
156161
157162 return nil
158163}
164+
165+ func (ur * userRepository ) MarkUserAsDeleted (ctx context.Context , tx * sqlx.Tx , userID int , deletedAt time.Time ) (User , error ) {
166+ executer := ur .BaseRepository .initiateQueryExecuter (tx )
167+ _ , err := executer .ExecContext (ctx , `UPDATE users SET is_deleted = TRUE, deleted_at=$1 WHERE id = $2` , deletedAt , userID )
168+ if err != nil {
169+ slog .Error ("unable to mark user as deleted" , "error" , err )
170+ return User {}, apperrors .ErrInternalServer
171+ }
172+ var user User
173+ err = executer .QueryRowContext (ctx , getUserByIdQuery , userID ).Scan (
174+ & user .Id ,
175+ & user .GithubId ,
176+ & user .GithubUsername ,
177+ & user .AvatarUrl ,
178+ & user .Email ,
179+ & user .CurrentActiveGoalId ,
180+ & user .CurrentBalance ,
181+ & user .IsBlocked ,
182+ & user .IsAdmin ,
183+ & user .Password ,
184+ & user .IsDeleted ,
185+ & user .DeletedAt ,
186+ & user .CreatedAt ,
187+ & user .UpdatedAt ,
188+ )
189+ if err != nil {
190+ if errors .Is (err , sql .ErrNoRows ) {
191+ slog .Error ("user not found" , "error" , err )
192+ return User {}, apperrors .ErrUserNotFound
193+ }
194+ slog .Error ("error occurred while getting user by id" , "error" , err )
195+ return User {}, apperrors .ErrInternalServer
196+ }
197+ return user , nil
198+ }
199+
200+ func (ur * userRepository ) AccountScheduledForDelete (ctx context.Context , tx * sqlx.Tx , userID int ) error {
201+ var deleteGracePeriod = 90 * 24 * time .Hour
202+ user , err := ur .GetUserById (ctx , tx , userID )
203+
204+ if err != nil {
205+ slog .Error ("unable to fetch user by ID " , "error" , err )
206+ return apperrors .ErrInternalServer
207+ }
208+
209+ if user .IsDeleted {
210+ var dlt_at time.Time
211+ if ! user .DeletedAt .Valid {
212+ return errors .New ("invalid deletion state" )
213+ } else {
214+ dlt_at = user .DeletedAt .Time
215+ }
216+
217+ if time .Since (dlt_at ) >= deleteGracePeriod {
218+ slog .Error ("user is permanentaly deleted " , "error" , err )
219+ return apperrors .ErrInternalServer
220+ } else {
221+ executer := ur .BaseRepository .initiateQueryExecuter (tx )
222+ _ , err := executer .ExecContext (ctx , `UPDATE users SET is_deleted = false, deleted_at = NULL WHERE id = $1` , userID )
223+ slog .Error ("unable to reverse the soft delete " , "error" , err )
224+ return apperrors .ErrInternalServer
225+ }
226+ }
227+ return nil
228+ }
229+
230+ func (ur * userRepository ) DeleteUser (tx * sqlx.Tx ) error {
231+ threshold := time .Now ().Add (- 90 * 1 * time .Second )
232+ executer := ur .BaseRepository .initiateQueryExecuter (tx )
233+ ctx := context .Background ()
234+ _ , err := executer .ExecContext (ctx , `DELETE FROM users WHERE is_deleted = TRUE AND deleted_at <= $1 ` , threshold )
235+ return err
236+ }
0 commit comments