From 544c1a52e5584477f65e47d133b35e0c00c94257 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Thu, 13 Apr 2023 20:52:39 -0400 Subject: [PATCH 01/16] Store and Retreive Token --- src/api/controllers/UserController.ts | 7 ++++++- src/models/UserModel.ts | 3 +++ src/repositories/UserRepository.ts | 5 +++++ src/services/NotifService.ts | 1 + src/services/UserService.ts | 11 ++++++++++- src/types/ApiRequests.ts | 4 ++++ src/types/ApiResponses.ts | 5 ----- 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/api/controllers/UserController.ts b/src/api/controllers/UserController.ts index 0c95b02..1b9c9c3 100644 --- a/src/api/controllers/UserController.ts +++ b/src/api/controllers/UserController.ts @@ -2,7 +2,7 @@ import { Body, CurrentUser, Get, JsonController, Param, Params, Post } from 'rou import { UserModel } from '../../models/UserModel'; import { UserService } from '../../services/UserService'; -import { EditProfileRequest, GetUserByEmailRequest, GetUserResponse, GetUsersResponse, SetAdminByEmailRequest } from '../../types'; +import { EditProfileRequest, GetUserByEmailRequest, GetUserResponse, GetUsersResponse, SaveTokenRequest, SetAdminByEmailRequest } from '../../types'; import { UuidParam } from '../validators/GenericRequests'; @JsonController('user/') @@ -48,4 +48,9 @@ export class UserController { async setAdmin(@Body() setAdminByEmailRequest: SetAdminByEmailRequest, @CurrentUser() superAdmin: UserModel): Promise { return { user: await this.userService.setAdmin(superAdmin, setAdminByEmailRequest) }; } + + @Post('token/') + async saveToken(@Body() saveTokenRequest: SaveTokenRequest): Promise { + return { user: await this.userService.saveToken(saveTokenRequest) }; + } } \ No newline at end of file diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts index 815dfeb..a235281 100644 --- a/src/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -39,6 +39,9 @@ export class UserModel { @Column({ unique: true }) googleId: string; + @Column({ unique: true}) + deviceToken: string; + @Column({ type: "text", default: "" }) bio: string; diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index d0379d2..b156083 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -129,4 +129,9 @@ export class UserRepository extends AbstractRepository { public async deleteUser(user: UserModel): Promise { return await this.repository.remove(user); } + + public async saveToken(user: UserModel, token: string): Promise { + user.deviceToken = token; + return await this.repository.save(user) + } } \ No newline at end of file diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 1caadbd..750f9b8 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -46,4 +46,5 @@ public sendNotifs = (notif : ExpoPushMessage, json = {}) => { // Simply do nothing if the user has no tokens catch (err) { console.log(err) } } + } \ No newline at end of file diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 36150da..f396e26 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -6,7 +6,7 @@ import { InjectManager } from 'typeorm-typedi-extensions'; import { UuidParam } from '../api/validators/GenericRequests'; import { UserModel } from '../models/UserModel'; import Repositories, { TransactionsManager } from '../repositories'; -import { EditProfileRequest, SetAdminByEmailRequest } from '../types'; +import { EditProfileRequest, SaveTokenRequest, SetAdminByEmailRequest } from '../types'; import { uploadImage } from '../utils/Requests'; @Service() @@ -86,4 +86,13 @@ export class UserService { return await userRepository.setAdmin(user, setAdminByEmailRequest.status); }); } + + public async saveToken(saveTokenRequest: SaveTokenRequest): Promise { + return this.transactions.readWrite(async (transactionalEntityManager) => { + const userRepository = Repositories.user(transactionalEntityManager); + const user = await userRepository.getUserById(saveTokenRequest.userID); + if (!user) throw new NotFoundError('User not found!'); + return await userRepository.saveToken(user, saveTokenRequest.token) + }); + } } \ No newline at end of file diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index 401ba60..31d383c 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -111,3 +111,7 @@ export interface ExpoPushMessage { data: JSON; } +export interface SaveTokenRequest { + token: string, + userID: Uuid; +} diff --git a/src/types/ApiResponses.ts b/src/types/ApiResponses.ts index 325d6d8..1cc585d 100644 --- a/src/types/ApiResponses.ts +++ b/src/types/ApiResponses.ts @@ -147,8 +147,3 @@ export interface PushTicket { data: PushTicketData[], errors: PushTicketErrorData[] } - -export interface SaveTokenRequest { - token: string, - email: string -} \ No newline at end of file From cd6c56654d75b727d3d1dc22e111316a759b30a9 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Sat, 15 Apr 2023 16:44:25 -0400 Subject: [PATCH 02/16] add models --- src/api/controllers/NotifController.ts | 7 ++++++- src/models/UserModel.ts | 2 +- src/repositories/UserRepository.ts | 7 ++++++- src/types/ApiRequests.ts | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/api/controllers/NotifController.ts b/src/api/controllers/NotifController.ts index 6508ab5..3e40d23 100644 --- a/src/api/controllers/NotifController.ts +++ b/src/api/controllers/NotifController.ts @@ -14,4 +14,9 @@ export class NotifController { async sendPost( notifRequest : ExpoPushMessage ) { return this.notifService.sendNotifs(notifRequest, {}); } -} \ No newline at end of file +} + +//TODO: +//The frontend sends in an email... We retrive the user and all of their tokens +//Create an ExpoPushMessage with all of those tokens +//Call SendNotifs on it \ No newline at end of file diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts index a235281..6987945 100644 --- a/src/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -40,7 +40,7 @@ export class UserModel { googleId: string; @Column({ unique: true}) - deviceToken: string; + deviceTokens: string[]; @Column({ type: "text", default: "" }) bio: string; diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index b156083..f826f66 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -131,7 +131,12 @@ export class UserRepository extends AbstractRepository { } public async saveToken(user: UserModel, token: string): Promise { - user.deviceToken = token; + if (!user.deviceTokens) { + user.deviceTokens = [] + } + else { + user.deviceTokens.push(token); + } return await this.repository.save(user) } } \ No newline at end of file diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index 31d383c..c951e5b 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -105,7 +105,7 @@ export interface CreateRequestRequest { // NOTIFICATION export interface ExpoPushMessage { to: string[]; - sound: 'default' | null; + sound: 'default'; title: string; body: string; data: JSON; From cb06d3da16e9af2e54ebc4d91befe74cf7e4f442 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Sat, 15 Apr 2023 20:44:38 -0400 Subject: [PATCH 03/16] Notifications using emails --- src/api/controllers/NotifController.ts | 6 +- src/services/NotifService.ts | 78 ++++++++++++++++---------- src/types/ApiRequests.ts | 7 +++ 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/src/api/controllers/NotifController.ts b/src/api/controllers/NotifController.ts index 3e40d23..7626edb 100644 --- a/src/api/controllers/NotifController.ts +++ b/src/api/controllers/NotifController.ts @@ -1,5 +1,5 @@ import { Body, CurrentUser, Delete, Get, JsonController, Params, Post } from 'routing-controllers'; -import { ExpoPushMessage, PushTicket } from 'src/types'; +import { ExpoPushMessage, PushTicket, FindTokensRequest } from 'src/types'; import { NotifService } from '../../services/NotifService'; @JsonController('notif/') @@ -11,8 +11,8 @@ export class NotifController { } @Post() - async sendPost( notifRequest : ExpoPushMessage ) { - return this.notifService.sendNotifs(notifRequest, {}); + async sendPost( findTokensRequest : FindTokensRequest ) { + return this.notifService.sendNotifs(findTokensRequest, {}); } } diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 750f9b8..919152e 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -1,10 +1,12 @@ +import { NotFoundError} from 'routing-controllers'; import { Service } from 'typedi'; -import { ExpoPushMessage, PushTicket } from '../types'; -// import { uploadImage } from '../utils/Requests'; +import { ExpoPushMessage, PushTicket, FindTokensRequest } from '../types'; import { Expo } from 'expo-server-sdk'; +import { UserRepository } from 'src/repositories/UserRepository'; const expoServer = new Expo({ accessToken: 'lohuh5OtdO1KS4I_kJGdE0PDtnxgV4GEpTiJAIoZ' }); + @Service() export class NotifService { // /** @@ -12,39 +14,55 @@ export class NotifService { // * @param {NotifObject[]} notifs an array of notification objects // * @param {Object} expoServer the server object to connect with // */ - public sendNotifChunks = async (notifs : ExpoPushMessage[], expoServer : Expo) => { - let chunks = expoServer.chunkPushNotifications(notifs); - let tickets = []; - for (let chunk of chunks) { - try { - let ticketChunk = await expoServer.sendPushNotificationsAsync(chunk); - // store tickets to check for notif status later - tickets.push(...ticketChunk); - } catch (err) { - console.log("Error while sending notif chunk"); + private userRepository: UserRepository + + public sendNotifChunks = async (notifs : ExpoPushMessage[], expoServer : Expo) => { + let chunks = expoServer.chunkPushNotifications(notifs); + let tickets = []; + + for (let chunk of chunks) { + try { + let ticketChunk = await expoServer.sendPushNotificationsAsync(chunk); + // store tickets to check for notif status later + tickets.push(...ticketChunk); + } catch (err) { + console.log("Error while sending notif chunk"); + } + console.log(tickets); } - console.log(tickets); } -} - -public sendNotifs = (notif : ExpoPushMessage, json = {}) => { - try { - let notifs : ExpoPushMessage[] = []; - notif.to.forEach(token => { - notifs.push({ - to: notif.to, - sound: notif.sound, - title: notif.title, - body: notif.body, - data: notif.data + + public async sendNotifs(request: FindTokensRequest, json = {}) { + let user = await this.userRepository.getUserByEmail(request.email); + if (!user) { + throw new NotFoundError('User not found!'); + } + let notif: ExpoPushMessage= + { + to: user.deviceTokens, + sound: 'default', + title: request.title, + body: request.body, + data: request.data + } + + try { + let notifs : ExpoPushMessage[] = []; + notif.to.forEach(token => { + notifs.push({ + to: notif.to, + sound: notif.sound, + title: notif.title, + body: notif.body, + data: notif.data + }) }) - }) - this.sendNotifChunks(notifs, expoServer) + this.sendNotifChunks(notifs, expoServer) + } + // Simply do nothing if the user has no tokens + catch (err) { console.log(err) } } - // Simply do nothing if the user has no tokens - catch (err) { console.log(err) } -} } \ No newline at end of file diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index c951e5b..c8668fe 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -115,3 +115,10 @@ export interface SaveTokenRequest { token: string, userID: Uuid; } + +export interface FindTokensRequest { + email: string + title: string; + body: string; + data: JSON; +} From 4a3e5c74a2a7e604788db3abe6d9eb4aa60b812e Mon Sep 17 00:00:00 2001 From: akmatchev Date: Wed, 26 Apr 2023 18:23:37 -0400 Subject: [PATCH 04/16] Add similar posts endpoint --- src/api/controllers/PostController.ts | 5 +++++ src/services/PostService.ts | 28 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/api/controllers/PostController.ts b/src/api/controllers/PostController.ts index a0f2384..436668a 100644 --- a/src/api/controllers/PostController.ts +++ b/src/api/controllers/PostController.ts @@ -102,4 +102,9 @@ export class PostController { async editPrice(@Body() editPriceRequest : EditPostPriceRequest, @CurrentUser() user: UserModel, @Params() params: UuidParam): Promise { return { new_price: await (await this.postService.editPostPrice(user, params, editPriceRequest)).altered_price }; } + + @Get('similar/postID/:id/') + async similarPosts(@Params() params: UuidParam): Promise { + return { posts: await this.postService.similarPosts(params) }; + } } \ No newline at end of file diff --git a/src/services/PostService.ts b/src/services/PostService.ts index 23ae2c2..a95e373 100644 --- a/src/services/PostService.ts +++ b/src/services/PostService.ts @@ -223,5 +223,33 @@ export class PostService { }, 0); return result; } + + public async similarPosts(params: UuidParam): Promise { + return this.transactions.readOnly(async (transactionalEntityManager) => { + const postRepository = Repositories.post(transactionalEntityManager); + const post = await postRepository.getPostById(params.id); + if (!post) throw new NotFoundError('Post not found!'); + const allPosts = await postRepository.getAllPosts(); + let posts: PostModel[] = [] + for (const p of allPosts) { + if (post.id != p.id) { + const model = await getLoadedModel(); + const sentences = [ + post.title, + p.title + ]; + await model.embed(sentences).then(async (embeddings: any) => { + embeddings = embeddings.arraySync() + const a = embeddings[0]; + const b = embeddings[1]; + if (this.similarity(a, b) >= 0.5) { + posts.push(p) + } + }); + } + } + return posts + }); + } } From 6a48fcd842c508eb6c5736c2c3ebe446b2046506 Mon Sep 17 00:00:00 2001 From: akmatchev Date: Wed, 26 Apr 2023 19:00:11 -0400 Subject: [PATCH 05/16] Fixed small incongruencies in urls of endpoints --- src/api/controllers/PostController.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/controllers/PostController.ts b/src/api/controllers/PostController.ts index 436668a..04d353e 100644 --- a/src/api/controllers/PostController.ts +++ b/src/api/controllers/PostController.ts @@ -98,12 +98,12 @@ export class PostController { return { isSaved: await this.postService.isSavedPost(user, params) }; } - @Post('edit/postID/:id/') + @Post('edit/postId/:id/') async editPrice(@Body() editPriceRequest : EditPostPriceRequest, @CurrentUser() user: UserModel, @Params() params: UuidParam): Promise { return { new_price: await (await this.postService.editPostPrice(user, params, editPriceRequest)).altered_price }; } - @Get('similar/postID/:id/') + @Get('similar/postId/:id/') async similarPosts(@Params() params: UuidParam): Promise { return { posts: await this.postService.similarPosts(params) }; } From 66b9354bae933f9965142489f090736ec37dd14c Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Wed, 26 Apr 2023 22:23:54 -0400 Subject: [PATCH 06/16] Implement store tokens and notifications --- src/api/controllers/NotifController.ts | 4 +- src/api/controllers/index.ts | 2 + src/api/validators/AuthControllerRequests.ts | 3 + src/migrations/0001_AddDeviceTokenForUser.ts | 21 +++++ .../1682461409919-AddDeviceTokenToSession.ts | 22 +++++ src/models/UserModel.ts | 3 +- src/models/UserSessionModel.ts | 4 + src/repositories/UserRepository.ts | 20 ++++- src/repositories/UserSessionRepository.ts | 1 + src/services/AuthService.ts | 13 +++ src/services/NotifService.ts | 81 ++++++++++++------- src/types/ApiRequests.ts | 5 +- src/types/ApiResponses.ts | 1 + src/types/Miscellaneous.ts | 1 + 14 files changed, 145 insertions(+), 36 deletions(-) create mode 100644 src/migrations/0001_AddDeviceTokenForUser.ts create mode 100644 src/migrations/1682461409919-AddDeviceTokenToSession.ts diff --git a/src/api/controllers/NotifController.ts b/src/api/controllers/NotifController.ts index 7626edb..5f6eb19 100644 --- a/src/api/controllers/NotifController.ts +++ b/src/api/controllers/NotifController.ts @@ -11,8 +11,8 @@ export class NotifController { } @Post() - async sendPost( findTokensRequest : FindTokensRequest ) { - return this.notifService.sendNotifs(findTokensRequest, {}); + async sendPost(@Body() findTokensRequest: FindTokensRequest) { + return this.notifService.sendNotifs(findTokensRequest); } } diff --git a/src/api/controllers/index.ts b/src/api/controllers/index.ts index 19f0dc0..aef2727 100644 --- a/src/api/controllers/index.ts +++ b/src/api/controllers/index.ts @@ -4,6 +4,7 @@ import { ImageController } from './ImageController'; import { PostController } from './PostController'; import { RequestController } from './RequestController'; import { UserController } from './UserController'; +import { NotifController } from './NotifController' export const controllers = [ AuthController, @@ -12,4 +13,5 @@ export const controllers = [ PostController, RequestController, UserController, + NotifController ]; \ No newline at end of file diff --git a/src/api/validators/AuthControllerRequests.ts b/src/api/validators/AuthControllerRequests.ts index 608e1ff..c4c521b 100644 --- a/src/api/validators/AuthControllerRequests.ts +++ b/src/api/validators/AuthControllerRequests.ts @@ -8,4 +8,7 @@ export class LoginRequest implements AuthRequest { @IsDefined() user: GoogleLoginUser; + + @IsDefined() + deviceToken: string; } \ No newline at end of file diff --git a/src/migrations/0001_AddDeviceTokenForUser.ts b/src/migrations/0001_AddDeviceTokenForUser.ts new file mode 100644 index 0000000..f86f47b --- /dev/null +++ b/src/migrations/0001_AddDeviceTokenForUser.ts @@ -0,0 +1,21 @@ +import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; + +const TABLE_NAME = "User"; + +export class AddDeviceTokenForUser1682226973547 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + // add device token for user table + await queryRunner.addColumn( + TABLE_NAME, + new TableColumn({ + name: "deviceTokens", + type: "text[]", + default: 'array[]::text[]', + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); + } +} diff --git a/src/migrations/1682461409919-AddDeviceTokenToSession.ts b/src/migrations/1682461409919-AddDeviceTokenToSession.ts new file mode 100644 index 0000000..3b691cc --- /dev/null +++ b/src/migrations/1682461409919-AddDeviceTokenToSession.ts @@ -0,0 +1,22 @@ +import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; + +const TABLE_NAME = "UserSession" + +export class AddDeviceTokenToSession1682461409919 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.addColumn( + TABLE_NAME, + new TableColumn({ + name: "deviceToken", + type: "text", + default: "''" + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); + } + +} diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts index 6987945..1b481cc 100644 --- a/src/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -39,7 +39,7 @@ export class UserModel { @Column({ unique: true }) googleId: string; - @Column({ unique: true}) + @Column("text", { array: true, default: [], nullable: false, }) deviceTokens: string[]; @Column({ type: "text", default: "" }) @@ -75,6 +75,7 @@ export class UserModel { bio: this.bio, posts: this.posts, feedbacks: this.feedbacks, + deviceTokens: this.deviceTokens, }; } } \ No newline at end of file diff --git a/src/models/UserSessionModel.ts b/src/models/UserSessionModel.ts index 3031a78..9c91ece 100644 --- a/src/models/UserSessionModel.ts +++ b/src/models/UserSessionModel.ts @@ -19,6 +19,9 @@ export class UserSessionModel { @Column() refreshToken: string; + @Column("text", { default: "", nullable: false, }) + deviceToken: string; + @ManyToOne(() => UserModel, user => user.sessions, { onDelete: "CASCADE" }) @JoinColumn({ name: 'user' }) user: UserModel; @@ -43,6 +46,7 @@ export class UserSessionModel { active: this.expiresAt.getTime() > Date.now(), expiresAt: this.expiresAt.getTime(), refreshToken: this.refreshToken, + deviceToken: this.deviceToken }; } diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index f826f66..e0d00ca 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -102,7 +102,7 @@ export class UserRepository extends AbstractRepository { username: string | undefined, photoUrl: string | undefined, venmoHandle: string | undefined, - bio: string | undefined + bio: string | undefined, ): Promise { const existingUser = this.repository .createQueryBuilder("user") @@ -121,6 +121,24 @@ export class UserRepository extends AbstractRepository { return await this.repository.save(user); } + public async addDeviceToken( + user: UserModel, + deviceTokens: string[] | undefined + ): Promise { + if (deviceTokens) { + user.deviceTokens = user.deviceTokens.concat(deviceTokens) + } + return await this.repository.save(user); + } + + public async removeDeviceToken( + user: UserModel, + deviceToken: string + ): Promise { + user.deviceTokens = user.deviceTokens.filter((e, i) => e !== deviceToken) + return await this.repository.save(user) + } + public async setAdmin(user: UserModel, status: boolean): Promise { user.admin = status; return await this.repository.save(user); diff --git a/src/repositories/UserSessionRepository.ts b/src/repositories/UserSessionRepository.ts index 7b6d5f1..909ea6f 100644 --- a/src/repositories/UserSessionRepository.ts +++ b/src/repositories/UserSessionRepository.ts @@ -11,6 +11,7 @@ export class UserSessionRepository extends AbstractRepository const session = new UserSessionModel(); session.user = user; session.userId = user.id; + session.deviceToken = user.deviceTokens[user.deviceTokens.length - 1] session.update(); await this.repository.save(session); return session; diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index babdf3a..ff0e5c3 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -68,6 +68,10 @@ export class AuthService { user = await userRepository.createUser(netid, netid, newUser.givenName, newUser.familyName, newUser.photoUrl, newUser.email, userId); } + //add device token + if (!user.deviceTokens.includes(authRequest.deviceToken)) { + userRepository.addDeviceToken(user, [authRequest.deviceToken]) + } // since they're logging in, create a new session for them const session = sessionsRepository.createSession(user); return session; @@ -102,8 +106,17 @@ export class AuthService { } public async deleteSessionByAccessToken(accessToken: string): Promise { + console.log(accessToken) return this.transactions.readWrite(async (transactionalEntityManager) => { const sessionRepository = Repositories.session(transactionalEntityManager); + const userRepository = Repositories.user(transactionalEntityManager); + const userID = await sessionRepository.getUserIdFromToken(accessToken); + if (!userID) throw new NotFoundError('UserID not found') + const user = await userRepository.getUserById(userID) + if (!user) throw new NotFoundError('User not found!') + const session = await sessionRepository.getSessionByToken(accessToken); + if (!session) throw new NotFoundError('Session not found!') + userRepository.removeDeviceToken(user, session.deviceToken); const success = await sessionRepository.deleteSessionByAccessToken(accessToken); return success; }); diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index b2e2039..14b4c57 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -3,6 +3,9 @@ import { Service } from 'typedi'; import { ExpoPushMessage, PushTicket, FindTokensRequest } from '../types'; import { Expo } from 'expo-server-sdk'; import { UserRepository } from 'src/repositories/UserRepository'; +import Repositories, { TransactionsManager } from '../repositories'; +import { EntityManager } from 'typeorm'; +import { InjectManager } from 'typeorm-typedi-extensions'; var accessToken = process.env['EXPO_ACCESS_TOKEN'] const expoServer = new Expo({ accessToken: accessToken }); @@ -15,16 +18,25 @@ export class NotifService { // * @param {Object} expoServer the server object to connect with // */ - private userRepository: UserRepository + private transactions: TransactionsManager; + + constructor(@InjectManager() entityManager: EntityManager) { + this.transactions = new TransactionsManager(entityManager); + } public sendNotifChunks = async (notifs : ExpoPushMessage[], expoServer : Expo) => { let chunks = expoServer.chunkPushNotifications(notifs); + console.log("7") let tickets = []; + // console.log(chunks) for (let chunk of chunks) { + console.log("here") try { + console.log("9") let ticketChunk = await expoServer.sendPushNotificationsAsync(chunk); // store tickets to check for notif status later + console.log("10") tickets.push(...ticketChunk); } catch (err) { console.log("Error while sending notif chunk"); @@ -33,36 +45,45 @@ export class NotifService { } } - public async sendNotifs(request: FindTokensRequest, json = {}) { - let user = await this.userRepository.getUserByEmail(request.email); - if (!user) { - throw new NotFoundError('User not found!'); - } - let notif: ExpoPushMessage= - { - to: user.deviceTokens, - sound: 'default', - title: request.title, - body: request.body, - data: request.data + public async sendNotifs(request: FindTokensRequest) { + // console.log(request) + return this.transactions.readWrite(async (transactionalEntityManager) => { + const userRepository = Repositories.user(transactionalEntityManager); + let user = await userRepository.getUserByEmail(request.email); + console.log("1") + if (!user) { + console.log("2") + throw new NotFoundError("User not found!"); } - - try { - let notifs : ExpoPushMessage[] = []; - notif.to.forEach(token => { - notifs.push({ - to: notif.to, - sound: notif.sound, - title: notif.title, - body: notif.body, - data: notif.data + console.log("3") + let notif: ExpoPushMessage= + { + to: user.deviceTokens, + sound: 'default', + title: request.title, + body: request.body, + data: request.data + } + // console.log(notif) + try { + let notifs : ExpoPushMessage[] = []; + console.log("5") + notif.to.forEach(token => { + notifs.push({ + to: [token], + sound: notif.sound, + title: notif.title, + body: notif.body, + data: notif.data + }) }) - }) - - this.sendNotifChunks(notifs, expoServer) - } - // Simply do nothing if the user has no tokens - catch (err) { console.log(err) } + console.log(notifs) + this.sendNotifChunks(notifs, expoServer) + } + // Simply do nothing if the user has no tokens + catch (err) { + console.log("hai"); + console.log(err) } + }) } - } \ No newline at end of file diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index c8668fe..11980b1 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -16,6 +16,7 @@ export interface GoogleLoginUser { export interface AuthRequest { idToken: string; user: GoogleLoginUser; + deviceToken: string } export interface EditProfileRequest { @@ -112,12 +113,12 @@ export interface ExpoPushMessage { } export interface SaveTokenRequest { - token: string, + token: string; userID: Uuid; } export interface FindTokensRequest { - email: string + email: string; title: string; body: string; data: JSON; diff --git a/src/types/ApiResponses.ts b/src/types/ApiResponses.ts index 1cc585d..16cb6f2 100644 --- a/src/types/ApiResponses.ts +++ b/src/types/ApiResponses.ts @@ -30,6 +30,7 @@ export interface PrivateProfile extends PublicProfile { email: string, googleId: string, feedbacks: FeedbackModel[], + deviceTokens: string[] } export interface GetUsersResponse { diff --git a/src/types/Miscellaneous.ts b/src/types/Miscellaneous.ts index b02c5d6..379627e 100644 --- a/src/types/Miscellaneous.ts +++ b/src/types/Miscellaneous.ts @@ -4,6 +4,7 @@ export type APIUserSession = { refreshToken: string, active: boolean, expiresAt: number, + deviceToken: string } export enum Category { From 7d80083ccf543ca81892c1dfce6aa3f0e5ad345f Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Fri, 28 Apr 2023 16:54:37 -0400 Subject: [PATCH 07/16] Requested changes on PR --- src/api/controllers/NotifController.ts | 6 +----- src/api/controllers/index.ts | 2 +- src/migrations/0001_AddDeviceTokenForUser.ts | 2 +- ...kenToSession.ts => 0003_AddDeviceTokenToSession.ts} | 0 src/repositories/UserRepository.ts | 10 ---------- src/services/NotifService.ts | 7 ------- src/types/ApiRequests.ts | 2 +- src/types/ApiResponses.ts | 2 +- 8 files changed, 5 insertions(+), 26 deletions(-) rename src/migrations/{1682461409919-AddDeviceTokenToSession.ts => 0003_AddDeviceTokenToSession.ts} (100%) diff --git a/src/api/controllers/NotifController.ts b/src/api/controllers/NotifController.ts index 5f6eb19..1b3dcfc 100644 --- a/src/api/controllers/NotifController.ts +++ b/src/api/controllers/NotifController.ts @@ -11,12 +11,8 @@ export class NotifController { } @Post() - async sendPost(@Body() findTokensRequest: FindTokensRequest) { + async sendNotif(@Body() findTokensRequest: FindTokensRequest) { return this.notifService.sendNotifs(findTokensRequest); } } -//TODO: -//The frontend sends in an email... We retrive the user and all of their tokens -//Create an ExpoPushMessage with all of those tokens -//Call SendNotifs on it \ No newline at end of file diff --git a/src/api/controllers/index.ts b/src/api/controllers/index.ts index aef2727..ee1334d 100644 --- a/src/api/controllers/index.ts +++ b/src/api/controllers/index.ts @@ -10,8 +10,8 @@ export const controllers = [ AuthController, FeedbackController, ImageController, + NotifController, PostController, RequestController, UserController, - NotifController ]; \ No newline at end of file diff --git a/src/migrations/0001_AddDeviceTokenForUser.ts b/src/migrations/0001_AddDeviceTokenForUser.ts index f86f47b..6897f9c 100644 --- a/src/migrations/0001_AddDeviceTokenForUser.ts +++ b/src/migrations/0001_AddDeviceTokenForUser.ts @@ -1,4 +1,4 @@ -import {MigrationInterface, QueryRunner, TableColumn} from "typeorm"; +import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; const TABLE_NAME = "User"; diff --git a/src/migrations/1682461409919-AddDeviceTokenToSession.ts b/src/migrations/0003_AddDeviceTokenToSession.ts similarity index 100% rename from src/migrations/1682461409919-AddDeviceTokenToSession.ts rename to src/migrations/0003_AddDeviceTokenToSession.ts diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index e0d00ca..872713c 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -147,14 +147,4 @@ export class UserRepository extends AbstractRepository { public async deleteUser(user: UserModel): Promise { return await this.repository.remove(user); } - - public async saveToken(user: UserModel, token: string): Promise { - if (!user.deviceTokens) { - user.deviceTokens = [] - } - else { - user.deviceTokens.push(token); - } - return await this.repository.save(user) - } } \ No newline at end of file diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 14b4c57..7950682 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -50,12 +50,9 @@ export class NotifService { return this.transactions.readWrite(async (transactionalEntityManager) => { const userRepository = Repositories.user(transactionalEntityManager); let user = await userRepository.getUserByEmail(request.email); - console.log("1") if (!user) { - console.log("2") throw new NotFoundError("User not found!"); } - console.log("3") let notif: ExpoPushMessage= { to: user.deviceTokens, @@ -64,10 +61,8 @@ export class NotifService { body: request.body, data: request.data } - // console.log(notif) try { let notifs : ExpoPushMessage[] = []; - console.log("5") notif.to.forEach(token => { notifs.push({ to: [token], @@ -77,12 +72,10 @@ export class NotifService { data: notif.data }) }) - console.log(notifs) this.sendNotifChunks(notifs, expoServer) } // Simply do nothing if the user has no tokens catch (err) { - console.log("hai"); console.log(err) } }) } diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index 11980b1..fe3e310 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -16,7 +16,7 @@ export interface GoogleLoginUser { export interface AuthRequest { idToken: string; user: GoogleLoginUser; - deviceToken: string + deviceToken: string; } export interface EditProfileRequest { diff --git a/src/types/ApiResponses.ts b/src/types/ApiResponses.ts index 16cb6f2..7e5b2e0 100644 --- a/src/types/ApiResponses.ts +++ b/src/types/ApiResponses.ts @@ -30,7 +30,7 @@ export interface PrivateProfile extends PublicProfile { email: string, googleId: string, feedbacks: FeedbackModel[], - deviceTokens: string[] + deviceTokens: string[], } export interface GetUsersResponse { From 16de822f4a9afb33e0e822cc93f867535e04f333 Mon Sep 17 00:00:00 2001 From: akmatchev Date: Sun, 30 Apr 2023 13:11:27 -0400 Subject: [PATCH 08/16] Loading model outside for loop --- src/services/PostService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/PostService.ts b/src/services/PostService.ts index a95e373..ec232e7 100644 --- a/src/services/PostService.ts +++ b/src/services/PostService.ts @@ -231,9 +231,9 @@ export class PostService { if (!post) throw new NotFoundError('Post not found!'); const allPosts = await postRepository.getAllPosts(); let posts: PostModel[] = [] + const model = await getLoadedModel(); for (const p of allPosts) { if (post.id != p.id) { - const model = await getLoadedModel(); const sentences = [ post.title, p.title From 6afe54c7ff738967f2e457fa119252cdadbb945a Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Mon, 1 May 2023 18:15:28 -0400 Subject: [PATCH 09/16] Further comment removal --- src/services/NotifService.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 7950682..1c99561 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -26,17 +26,12 @@ export class NotifService { public sendNotifChunks = async (notifs : ExpoPushMessage[], expoServer : Expo) => { let chunks = expoServer.chunkPushNotifications(notifs); - console.log("7") let tickets = []; - // console.log(chunks) for (let chunk of chunks) { - console.log("here") try { - console.log("9") let ticketChunk = await expoServer.sendPushNotificationsAsync(chunk); // store tickets to check for notif status later - console.log("10") tickets.push(...ticketChunk); } catch (err) { console.log("Error while sending notif chunk"); @@ -46,7 +41,6 @@ export class NotifService { } public async sendNotifs(request: FindTokensRequest) { - // console.log(request) return this.transactions.readWrite(async (transactionalEntityManager) => { const userRepository = Repositories.user(transactionalEntityManager); let user = await userRepository.getUserByEmail(request.email); From 547eb189d3cda2aba1db4a175b6804ac53a4cff1 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Mon, 1 May 2023 21:05:54 -0400 Subject: [PATCH 10/16] Another comment removal --- src/services/AuthService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index ff0e5c3..8b3a39c 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -106,7 +106,6 @@ export class AuthService { } public async deleteSessionByAccessToken(accessToken: string): Promise { - console.log(accessToken) return this.transactions.readWrite(async (transactionalEntityManager) => { const sessionRepository = Repositories.session(transactionalEntityManager); const userRepository = Repositories.user(transactionalEntityManager); From 049637226c04cec01841d1f84dd674d113bea4dc Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Tue, 2 May 2023 20:14:39 -0400 Subject: [PATCH 11/16] Remove usage of devicetoken on user model --- src/api/controllers/UserController.ts | 8 ++++---- src/repositories/UserSessionRepository.ts | 7 ++++++- src/services/AuthService.ts | 9 +++++---- src/services/NotifService.ts | 10 +++++++++- src/services/UserService.ts | 16 ++++++++-------- src/types/ApiResponses.ts | 13 +++++++++---- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/api/controllers/UserController.ts b/src/api/controllers/UserController.ts index 1b9c9c3..bc5e83f 100644 --- a/src/api/controllers/UserController.ts +++ b/src/api/controllers/UserController.ts @@ -49,8 +49,8 @@ export class UserController { return { user: await this.userService.setAdmin(superAdmin, setAdminByEmailRequest) }; } - @Post('token/') - async saveToken(@Body() saveTokenRequest: SaveTokenRequest): Promise { - return { user: await this.userService.saveToken(saveTokenRequest) }; - } + // @Post('token/') + // async saveToken(@Body() saveTokenRequest: SaveTokenRequest): Promise { + // return { user: await this.userService.saveToken(saveTokenRequest) }; + // } } \ No newline at end of file diff --git a/src/repositories/UserSessionRepository.ts b/src/repositories/UserSessionRepository.ts index 909ea6f..87f5fec 100644 --- a/src/repositories/UserSessionRepository.ts +++ b/src/repositories/UserSessionRepository.ts @@ -11,7 +11,7 @@ export class UserSessionRepository extends AbstractRepository const session = new UserSessionModel(); session.user = user; session.userId = user.id; - session.deviceToken = user.deviceTokens[user.deviceTokens.length - 1] + session.deviceToken = ''; session.update(); await this.repository.save(session); return session; @@ -101,6 +101,11 @@ export class UserSessionRepository extends AbstractRepository return session; } + public async updateSessionDeviceToken(session: UserSessionModel, deviceToken: string): Promise { + session.deviceToken = deviceToken; + return await this.repository.save(session); + } + public async verifySession(accessToken: string): Promise { const session = await this.repository .createQueryBuilder("UserSessionModel") diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 8b3a39c..533fa69 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -69,11 +69,12 @@ export class AuthService { newUser.photoUrl, newUser.email, userId); } //add device token - if (!user.deviceTokens.includes(authRequest.deviceToken)) { - userRepository.addDeviceToken(user, [authRequest.deviceToken]) - } + // if (!user.deviceTokens.includes(authRequest.deviceToken)) { + // userRepository.addDeviceToken(user, [authRequest.deviceToken]) + // } // since they're logging in, create a new session for them - const session = sessionsRepository.createSession(user); + const session = await sessionsRepository.createSession(user); + sessionsRepository.updateSessionDeviceToken(session, authRequest.deviceToken) return session; }); } diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 1c99561..2e9c1a9 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -43,13 +43,20 @@ export class NotifService { public async sendNotifs(request: FindTokensRequest) { return this.transactions.readWrite(async (transactionalEntityManager) => { const userRepository = Repositories.user(transactionalEntityManager); + const userSessionRepository = Repositories.session(transactionalEntityManager); let user = await userRepository.getUserByEmail(request.email); if (!user) { throw new NotFoundError("User not found!"); } + const allDeviceTokens = []; + const allsessions = await userSessionRepository.getSessionsByUserId(user.id); + for (var sess of allsessions) { + if (sess.deviceToken) { + allDeviceTokens.push(sess.deviceToken); } + } let notif: ExpoPushMessage= { - to: user.deviceTokens, + to: allDeviceTokens, sound: 'default', title: request.title, body: request.body, @@ -68,6 +75,7 @@ export class NotifService { }) this.sendNotifChunks(notifs, expoServer) } + // Simply do nothing if the user has no tokens catch (err) { console.log(err) } diff --git a/src/services/UserService.ts b/src/services/UserService.ts index f396e26..1b80898 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -87,12 +87,12 @@ export class UserService { }); } - public async saveToken(saveTokenRequest: SaveTokenRequest): Promise { - return this.transactions.readWrite(async (transactionalEntityManager) => { - const userRepository = Repositories.user(transactionalEntityManager); - const user = await userRepository.getUserById(saveTokenRequest.userID); - if (!user) throw new NotFoundError('User not found!'); - return await userRepository.saveToken(user, saveTokenRequest.token) - }); - } + // public async saveToken(saveTokenRequest: SaveTokenRequest): Promise { + // return this.transactions.readWrite(async (transactionalEntityManager) => { + // const userRepository = Repositories.user(transactionalEntityManager); + // const user = await userRepository.getUserById(saveTokenRequest.userID); + // if (!user) throw new NotFoundError('User not found!'); + // return await userRepository.saveToken(user, saveTokenRequest.token) + // }); + // } } \ No newline at end of file diff --git a/src/types/ApiResponses.ts b/src/types/ApiResponses.ts index 7e5b2e0..be6f6e0 100644 --- a/src/types/ApiResponses.ts +++ b/src/types/ApiResponses.ts @@ -135,16 +135,21 @@ export interface GetRequestResponse { export interface PushTicketData { status: string, id: string, - message: string - details: JSON + message: string, + details: JSON, } export interface PushTicketErrorData { code: string, - message: string + message: string, } export interface PushTicket { data: PushTicketData[], - errors: PushTicketErrorData[] + errors: PushTicketErrorData[], +} + +export interface NotifSent { + status: string, + id: string, } From 455643e7177ffb7188c239acd7222d2ec2918698 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Fri, 5 May 2023 13:44:19 -0400 Subject: [PATCH 12/16] More comment fixes & changes --- src/migrations/0001_AddDeviceTokenForUser.ts | 21 ------------------- .../0003_AddDeviceTokenToSession.ts | 2 +- src/models/UserModel.ts | 4 ---- src/repositories/UserRepository.ts | 18 ---------------- src/services/AuthService.ts | 12 ----------- src/services/NotifService.ts | 2 +- src/types/ApiResponses.ts | 2 -- 7 files changed, 2 insertions(+), 59 deletions(-) delete mode 100644 src/migrations/0001_AddDeviceTokenForUser.ts diff --git a/src/migrations/0001_AddDeviceTokenForUser.ts b/src/migrations/0001_AddDeviceTokenForUser.ts deleted file mode 100644 index 6897f9c..0000000 --- a/src/migrations/0001_AddDeviceTokenForUser.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; - -const TABLE_NAME = "User"; - -export class AddDeviceTokenForUser1682226973547 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - // add device token for user table - await queryRunner.addColumn( - TABLE_NAME, - new TableColumn({ - name: "deviceTokens", - type: "text[]", - default: 'array[]::text[]', - }) - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); - } -} diff --git a/src/migrations/0003_AddDeviceTokenToSession.ts b/src/migrations/0003_AddDeviceTokenToSession.ts index 3b691cc..f34b6e7 100644 --- a/src/migrations/0003_AddDeviceTokenToSession.ts +++ b/src/migrations/0003_AddDeviceTokenToSession.ts @@ -16,7 +16,7 @@ export class AddDeviceTokenToSession1682461409919 implements MigrationInterface } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); + await queryRunner.dropColumn(TABLE_NAME, "deviceToken"); } } diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts index 1b481cc..815dfeb 100644 --- a/src/models/UserModel.ts +++ b/src/models/UserModel.ts @@ -39,9 +39,6 @@ export class UserModel { @Column({ unique: true }) googleId: string; - @Column("text", { array: true, default: [], nullable: false, }) - deviceTokens: string[]; - @Column({ type: "text", default: "" }) bio: string; @@ -75,7 +72,6 @@ export class UserModel { bio: this.bio, posts: this.posts, feedbacks: this.feedbacks, - deviceTokens: this.deviceTokens, }; } } \ No newline at end of file diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index 872713c..22cdb4b 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -121,24 +121,6 @@ export class UserRepository extends AbstractRepository { return await this.repository.save(user); } - public async addDeviceToken( - user: UserModel, - deviceTokens: string[] | undefined - ): Promise { - if (deviceTokens) { - user.deviceTokens = user.deviceTokens.concat(deviceTokens) - } - return await this.repository.save(user); - } - - public async removeDeviceToken( - user: UserModel, - deviceToken: string - ): Promise { - user.deviceTokens = user.deviceTokens.filter((e, i) => e !== deviceToken) - return await this.repository.save(user) - } - public async setAdmin(user: UserModel, status: boolean): Promise { user.admin = status; return await this.repository.save(user); diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 533fa69..e269b1f 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -69,10 +69,6 @@ export class AuthService { newUser.photoUrl, newUser.email, userId); } //add device token - // if (!user.deviceTokens.includes(authRequest.deviceToken)) { - // userRepository.addDeviceToken(user, [authRequest.deviceToken]) - // } - // since they're logging in, create a new session for them const session = await sessionsRepository.createSession(user); sessionsRepository.updateSessionDeviceToken(session, authRequest.deviceToken) return session; @@ -109,14 +105,6 @@ export class AuthService { public async deleteSessionByAccessToken(accessToken: string): Promise { return this.transactions.readWrite(async (transactionalEntityManager) => { const sessionRepository = Repositories.session(transactionalEntityManager); - const userRepository = Repositories.user(transactionalEntityManager); - const userID = await sessionRepository.getUserIdFromToken(accessToken); - if (!userID) throw new NotFoundError('UserID not found') - const user = await userRepository.getUserById(userID) - if (!user) throw new NotFoundError('User not found!') - const session = await sessionRepository.getSessionByToken(accessToken); - if (!session) throw new NotFoundError('Session not found!') - userRepository.removeDeviceToken(user, session.deviceToken); const success = await sessionRepository.deleteSessionByAccessToken(accessToken); return success; }); diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 2e9c1a9..83170e0 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -1,6 +1,6 @@ import { NotFoundError} from 'routing-controllers'; import { Service } from 'typedi'; -import { ExpoPushMessage, PushTicket, FindTokensRequest } from '../types'; +import { ExpoPushMessage, PushTicket, FindTokensRequest, NotifSent } from '../types'; import { Expo } from 'expo-server-sdk'; import { UserRepository } from 'src/repositories/UserRepository'; import Repositories, { TransactionsManager } from '../repositories'; diff --git a/src/types/ApiResponses.ts b/src/types/ApiResponses.ts index be6f6e0..2d0b5d9 100644 --- a/src/types/ApiResponses.ts +++ b/src/types/ApiResponses.ts @@ -30,7 +30,6 @@ export interface PrivateProfile extends PublicProfile { email: string, googleId: string, feedbacks: FeedbackModel[], - deviceTokens: string[], } export interface GetUsersResponse { @@ -151,5 +150,4 @@ export interface PushTicket { export interface NotifSent { status: string, - id: string, } From afe2a9ff00d121d41caae0817d691318c4a8180a Mon Sep 17 00:00:00 2001 From: Shungo Najima Date: Fri, 5 May 2023 17:45:37 -0400 Subject: [PATCH 13/16] Readd migration files --- .gitignore | 1 + src/migrations/0001_AddDeviceTokenForUser.ts | 21 ++++++++++++++++++ .../0004_RemoveDeviceTokenForUser.ts | 22 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/migrations/0001_AddDeviceTokenForUser.ts create mode 100644 src/migrations/0004_RemoveDeviceTokenForUser.ts diff --git a/.gitignore b/.gitignore index 5d6f093..7b0f2e4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dist/ node_modules/ package-lock.json yarn.lock +*.DS_Store \ No newline at end of file diff --git a/src/migrations/0001_AddDeviceTokenForUser.ts b/src/migrations/0001_AddDeviceTokenForUser.ts new file mode 100644 index 0000000..39d29ca --- /dev/null +++ b/src/migrations/0001_AddDeviceTokenForUser.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner, TableColumn } from "typeorm"; + +const TABLE_NAME = "User"; + +export class AddDeviceTokenForUser1682226973547 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + // add device token for user table + await queryRunner.addColumn( + TABLE_NAME, + new TableColumn({ + name: "deviceTokens", + type: "text[]", + default: 'array[]::text[]', + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); + } +} \ No newline at end of file diff --git a/src/migrations/0004_RemoveDeviceTokenForUser.ts b/src/migrations/0004_RemoveDeviceTokenForUser.ts new file mode 100644 index 0000000..8645088 --- /dev/null +++ b/src/migrations/0004_RemoveDeviceTokenForUser.ts @@ -0,0 +1,22 @@ +import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; + +const TABLE_NAME = "User"; + +export class RemoveDeviceTokenForUser1683322987029 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn(TABLE_NAME, "deviceTokens"); + } + + public async down(queryRunner: QueryRunner): Promise { + // add device token for user table + await queryRunner.addColumn( + TABLE_NAME, + new TableColumn({ + name: "deviceTokens", + type: "text[]", + default: 'array[]::text[]', + }) + ); + } +} From d3e919cf5beec1e45dfd71775fd87383d4bd3b6a Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Sat, 6 May 2023 15:50:42 -0400 Subject: [PATCH 14/16] Last comment removal --- src/api/controllers/UserController.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/api/controllers/UserController.ts b/src/api/controllers/UserController.ts index bc5e83f..810580e 100644 --- a/src/api/controllers/UserController.ts +++ b/src/api/controllers/UserController.ts @@ -48,9 +48,4 @@ export class UserController { async setAdmin(@Body() setAdminByEmailRequest: SetAdminByEmailRequest, @CurrentUser() superAdmin: UserModel): Promise { return { user: await this.userService.setAdmin(superAdmin, setAdminByEmailRequest) }; } - - // @Post('token/') - // async saveToken(@Body() saveTokenRequest: SaveTokenRequest): Promise { - // return { user: await this.userService.saveToken(saveTokenRequest) }; - // } } \ No newline at end of file From c8fd7d3f5fa04bcafcc4dcec1c4b2d56806316b6 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Sat, 6 May 2023 19:50:46 -0400 Subject: [PATCH 15/16] Add 'default' type comment, remove commented code, remove devicetoken default assignment --- src/repositories/UserSessionRepository.ts | 1 - src/services/UserService.ts | 9 --------- src/types/ApiRequests.ts | 1 + 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/repositories/UserSessionRepository.ts b/src/repositories/UserSessionRepository.ts index 87f5fec..d46d964 100644 --- a/src/repositories/UserSessionRepository.ts +++ b/src/repositories/UserSessionRepository.ts @@ -11,7 +11,6 @@ export class UserSessionRepository extends AbstractRepository const session = new UserSessionModel(); session.user = user; session.userId = user.id; - session.deviceToken = ''; session.update(); await this.repository.save(session); return session; diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 1b80898..2277ccd 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -86,13 +86,4 @@ export class UserService { return await userRepository.setAdmin(user, setAdminByEmailRequest.status); }); } - - // public async saveToken(saveTokenRequest: SaveTokenRequest): Promise { - // return this.transactions.readWrite(async (transactionalEntityManager) => { - // const userRepository = Repositories.user(transactionalEntityManager); - // const user = await userRepository.getUserById(saveTokenRequest.userID); - // if (!user) throw new NotFoundError('User not found!'); - // return await userRepository.saveToken(user, saveTokenRequest.token) - // }); - // } } \ No newline at end of file diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index fe3e310..43562e9 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -106,6 +106,7 @@ export interface CreateRequestRequest { // NOTIFICATION export interface ExpoPushMessage { to: string[]; + //special type for ExpoPushMessage sound: 'default'; title: string; body: string; From f32f01f1f1b2037e01fb78cc35beca226a953ca1 Mon Sep 17 00:00:00 2001 From: Joyce Wu Date: Wed, 10 May 2023 22:25:26 -0400 Subject: [PATCH 16/16] Fix minor issues --- src/services/NotifService.ts | 12 ++++++------ src/types/ApiRequests.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/services/NotifService.ts b/src/services/NotifService.ts index 83170e0..184d7cf 100644 --- a/src/services/NotifService.ts +++ b/src/services/NotifService.ts @@ -12,18 +12,18 @@ const expoServer = new Expo({ accessToken: accessToken }); @Service() export class NotifService { -// /** -// * Takes an array of notifications and sends them to users in batches (called chunks) -// * @param {NotifObject[]} notifs an array of notification objects -// * @param {Object} expoServer the server object to connect with -// */ - private transactions: TransactionsManager; constructor(@InjectManager() entityManager: EntityManager) { this.transactions = new TransactionsManager(entityManager); } + // /** +// * Takes an array of notifications and sends them to users in batches (called chunks) +// * @param {NotifObject[]} notifs an array of notification objects +// * @param {Object} expoServer the server object to connect with +// */ + public sendNotifChunks = async (notifs : ExpoPushMessage[], expoServer : Expo) => { let chunks = expoServer.chunkPushNotifications(notifs); let tickets = []; diff --git a/src/types/ApiRequests.ts b/src/types/ApiRequests.ts index 43562e9..1510261 100644 --- a/src/types/ApiRequests.ts +++ b/src/types/ApiRequests.ts @@ -115,7 +115,7 @@ export interface ExpoPushMessage { export interface SaveTokenRequest { token: string; - userID: Uuid; + userId: Uuid; } export interface FindTokensRequest {