merge stuff

This commit is contained in:
Me
2023-01-05 12:33:51 +01:00
19 changed files with 977 additions and 21511 deletions

View File

@@ -0,0 +1,22 @@
NODE_ENV=development
POSTGRES_HOST=postgresql
POSTGRES_PORT=5432
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=9pKpKEgiamxwk5P7Ggsz
POSTGRES_DATABASE=transcendance_db
# OAUTH2 42 API
FORTYTWO_CLIENT_ID=u-s4t2ud-49dc7b539bcfe1acb48b928b2b281671c99fc5bfab1faca57a536ab7e0075500
FORTYTWO_CLIENT_SECRET=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
FORTYTWO_CALLBACK_URL=http://transcendance:8080/api/v2/auth/redirect
COOKIE_SECRET=248cdc831110eec8796d7c1edbf79835
# JWT
JWT_SECRET=442d774798979fcc14a4a2b6b7535902
# Misc
PORT=3000
#Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=1a5e04138b91b3d683c708e4689454c2
#2fa
TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance

View File

@@ -27,10 +27,13 @@ export class ChatGateway
// how to guard the handleConnection ?
// https://github.com/nestjs/nest/issues/882
async handleConnection(client) {
const paginationQuery = new PaginationQueryDto();
const users = await this.usersService.findAll(paginationQuery);
// const paginationQuery = new PaginationQueryDto();
// const users = await this.usersService.findAll(paginationQuery);
// const users = await this.usersService.findAll(client);
// const users = await this.usersService.findAll(client);
console.log('---- Client connected :', client.id);
console.log('users :', users);
// console.log('users :', users);
}
handleDisconnect(client) {
console.log('---- client disconnected :', client.id);

View File

@@ -2,8 +2,8 @@ import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
import { FriendshipStatus } from '../entities/friendship.entity';
export class CreateFriendshipDto {
@IsString()
@IsNotEmpty()
@IsString()
readonly receiverUsername: string;
@IsEnum(FriendshipStatus)
readonly status: FriendshipStatus;

View File

@@ -23,12 +23,6 @@ export class Friendship {
@ManyToOne(type => User, user => user.username)
receiver: User;
@Column()
senderUsername : string;
@Column()
receiverUsername : string;
@Column({ type: 'enum', enum: FriendshipStatus, default: FriendshipStatus.REQUESTED})
status: FriendshipStatus;
}

View File

@@ -8,87 +8,72 @@ import { FriendshipService } from './friendship.service';
export class FriendshipController {
constructor(private readonly friendshipService: FriendshipService) { }
// new and improved finder of people
// GET http://transcendance:8080/api/v2/network/myfriends
@Get('myfriends')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
findEmpty(@Req() req) {
findOne(@Query('username') otherUsername: string, @Req() req) {
console.log('GET myfriends')
const user = req.user;
return this.friendshipService.findAllFriends(user.id);
if (otherUsername !== undefined) {
console.log('my friend: ' + otherUsername)
return this.friendshipService.findOneRelationshipByUsername(otherUsername, user.username);
}
return this.friendshipService.findAllFriendships(user.id);
// return this.friendshipService.findAllFriends(user.id);
}
// GET http://transcendance:8080/api/v2/network/myfriends/relationshipId
@Get('myfriend/:relationshipId')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
findOneFriend(@Param('relationshipId') relationshipId: string, @Req() req) {
const user = req.user;
return this.friendshipService.findOneFriend(relationshipId, user.username);
}
// GET http://transcendance:8080/api/v2/network/blocked
@Get('blocked')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
findAllBlocked(@Req() req) {
const user = req.user;
return this.friendshipService.findAllBlockedFriends(user.username);
}
@Get('blocked/:relationshipId')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
findOneBlocked(@Param('relationshipId') relationshipId: string, @Req() req) {
const user = req.user;
return this.friendshipService.findOneBlocked(relationshipId, user.username);
}
// POST http://transcendance:8080/api/v2/network/myfriends
@Post('myfriends')
// POST http://transcendance:8080/api/v2/network/relations
@Post('relations')
@HttpCode(HttpStatus.CREATED)
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
create(@Body() createFriendshipDto: CreateFriendshipDto, @Req() req) {
console.log('friendship.service create')
const user = req.user;
if (user.username !== createFriendshipDto.receiverUsername)
if (user.username !== createFriendshipDto.receiverUsername) {
console.log('friendship.service create have a receiver name')
return this.friendshipService.create(createFriendshipDto, user);
}
return new HttpException('You can\'t request a frienship to yourself', HttpStatus.BAD_REQUEST);
}
// PATCH http://transcendance:8080/api/v2/network/myfriends/relationshipId/accept
@Patch('myfriends/:relationshipId/accept')
// PATCH http://transcendance:8080/api/v2/network/relations/:relationshipId/accept
@Patch('relations/:relationshipId/accept')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
updateAccept(@Param('relationshipId') relationshipId: string, @Req() req)
{
updateAccept(@Param('relationshipId') relationshipId: number, @Req() req) {
const user : User = req.user;
return this.friendshipService.acceptFriendship(relationshipId, user);
}
@Patch('myfriends/:relationshipId/decline')
// PATCH http://transcendance:8080/api/v2/network/relations/:relationshipId/decline
@Patch('relations/:relationshipId/decline')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
updateDecline(@Param('relationshipId') relationshipId: string, @Req() req)
{
updateDecline(@Param('relationshipId') relationshipId: number, @Req() req) {
const user : User = req.user;
return this.friendshipService.declineFriendship(relationshipId, user);
}
@Patch('myfriends/:relationshipId/block')
// PATCH http://transcendance:8080/api/v2/network/relations/:relationshipId/block
@Patch('relations/:relationshipId/block')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
updateBlock(@Param('relationshipId') relationshipId: string, @Req() req)
{
updateBlock(@Param('relationshipId') relationshipId: number, @Req() req) {
const user : User = req.user;
return this.friendshipService.blockFriendship(relationshipId, user);
}
// DELETE http://transcendance:8080/api/v2/network/myfriends/relationshipId
@Delete(':relationshipId')
// DELETE http://transcendance:8080/api/v2/network/relations/:relationshipId
@Delete('relations/:relationshipId')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
remove(@Param('relationshipId') relationshipId: string, @Req() req) {
remove(@Param('relationshipId') relationshipId: number, @Req() req) {
const user : User = req.user;
console.log('deleting a friendship')
return this.friendshipService.removeFriendship(relationshipId, user);
}
@@ -98,7 +83,7 @@ export class FriendshipController {
@UseGuards(TwoFactorGuard)
findAllPendantFriendshipRequested(@Req() req) {
const user = req.user;
return this.friendshipService.findAllPendantRequestsForFriendship(user.username);
return this.friendshipService.findAllPendantRequestsForFriendship(user.id.toString());
}
// GET http://transcendance:8080/api/v2/network/received
@@ -107,6 +92,29 @@ export class FriendshipController {
@UseGuards(TwoFactorGuard)
findAllPendantFriendshipReceived(@Req() req) {
const user = req.user;
return this.friendshipService.findAllReceivedRequestsForFriendship(user.username);
return this.friendshipService.findAllReceivedRequestsForFriendship(user.id);
}
// GET http://transcendance:8080/api/v2/network/blocked
@Get('blocked')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
findBlocked(@Query('relationshipId') relationshipId: number, @Req() req) {
console.log('friendship.controller fetching blocked users')
console.log(relationshipId)
const user = req.user;
// if (relationshipId === undefined)
if (Number.isNaN(relationshipId))
return this.friendshipService.findAllBlockedFriends(user.id);
else
return this.friendshipService.findOneBlocked(relationshipId, user.id);
}
// @Get('blocked/:relationshipId')
// @UseGuards(AuthenticateGuard)
// @UseGuards(TwoFactorGuard)
// findOneBlocked(@Param('relationshipId') relationshipId: string, @Req() req) {
// const user = req.user;
// return this.friendshipService.findOneBlocked(relationshipId, user.username);
// }
}

View File

@@ -1,9 +1,11 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from 'src/users/entities/user.entity';
import { Repository } from 'typeorm';
import { SendableUser } from 'src/users/sendableUsers';
import { Repository, Brackets } from 'typeorm';
import { CreateFriendshipDto } from './dto/create-friendship.dto';
import { Friendship, FriendshipStatus } from './entities/friendship.entity';
import { SendableFriendship } from './sendableFriendship';
@Injectable()
export class FriendshipService {
@@ -16,84 +18,256 @@ export class FriendshipService {
) { }
async findOneFriend(friendshipId: string, username: string) {
const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.ACCEPTED } });
if (!friendship)
throw new HttpException(`The requested friend not found.`, HttpStatus.NOT_FOUND);
return friendship;
}
// createSendableFriendship(friendship: Friendship): SendableFriendship {
// let ret = new SendableFriendship;
async findOneBlocked(friendshipId: string, username: string) {
const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.BLOCKED } });
if (!friendship)
throw new HttpException(`The requested blocked not found.`, HttpStatus.NOT_FOUND);
return friendship;
}
// ret.id = friendship.id;
// ret.date = friendship.date
// ret.senderUsername = friendship.sender.username;
// ret.senderId = friendship.sender.id;
// ret.receiverUsername = friendship.receiver.username;
// ret.receiverId = friendship.receiver.id;
// ret.status = friendship.status;
// return ret;
// };
async findAllFriends(username: string) {
//kinda useless but someone else might use it
async findOneRelationshipById(friendId : number, userId : number) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where(
new Brackets((qb) => {
qb.where(
new Brackets((subAQb) => {
subAQb.where('sender.id = :userId', { userId : userId})
.andWhere('receiver.id = :friendId', {friendId : friendId})
})
)
.orWhere(
new Brackets((subBQb) => {
subBQb.where('sender.id = :friendId2', {friendId2 : friendId})
.andWhere('receiver.id = :userId2', {userId2 : userId})
})
)
}),
)
// .andWhere('friendship.status != :status', {status : FriendshipStatus.BLOCKED})
.getOne()
console.log('END Find one friend by ID: ')
console.log({...friendship})
if (!friendship) {
throw new HttpException(`There is no such friendship`, HttpStatus.NOT_FOUND);
}
// return friendship;
// return this.createSendableFriendship(friendship);
return new SendableFriendship(friendship);
}
async findOneRelationshipByUsername(friendUsername : string, username : string) {
// This seems to work, finding friendships by username but checking the actual users not the friendship
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where(
new Brackets((qb) => {
qb.where(
new Brackets((subAQb) => {
subAQb.where('sender.username = :username', {username : username})
.andWhere('receiver.username = :friendUsername', {friendUsername : friendUsername})
})
)
.orWhere(
new Brackets((subBQb) => {
subBQb.where('sender.username = :friendUsername2', {friendUsername2 : friendUsername})
.andWhere('receiver.username = :username2', {username2 : username})
})
)
}),
)
// .andWhere('friendship.status != :status', {status : FriendshipStatus.BLOCKED})
.getOne()
console.log('END Find one friend by username: ')
console.log({...friendship})
if (!friendship) {
throw new HttpException(`There is no such friendship`, HttpStatus.NOT_FOUND);
}
// return friendship;
return new SendableFriendship(friendship);
}
// maybe i should be returning a list of users not a list of friendships
// async findAllFriends(userId: number) {
async findAllFriendships(userId: number) {
const friendships = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.status = :status', { status: FriendshipStatus.ACCEPTED })
.andWhere('friendship.receiverUsername = :addressee', { addressee: username })
.orWhere('friendship.senderUsername = :requester', { requester: username })
.andWhere('receiver.id = :addressee', { addressee: userId })
.orWhere('sender.id = :requester', { requester: userId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.ACCEPTED })
.getMany();
for (const friend of friendship)
console.log("FRIENDSHIP : " + friend.status);
return friendship;
}
async findAllBlockedFriends(username: string) {
const friendships : Friendship[] = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
// for (const friend of friendship)
// console.log("FRIENDSHIP : " + friend.status);
// return friendship;
let sendFrienships: SendableFriendship[] = [];
for (const friendship of friendships) {
partialFriendship.push({id: friendship.id, date: friendship.date, senderUsername: friendship.senderUsername, receiverUsername: friendship.receiverUsername, status: friendship.status});
sendFrienships.push(new SendableFriendship(friendship));
}
return partialFriendship;
// return new SendableFriendship(friendship);
console.log('friendship.service my friends:')
console.log({...sendFrienships})
return sendFrienships;
// let sendFriends: SendableUser[] = [];
// for (const friendship of friendships) {
// let user: User;
// if (friendship.sender.id !== userId)
// user = friendship.sender;
// else
// user = friendship.receiver;
// sendFriends.push(new SendableUser(user));
// }
// console.log('friendship.service my friends as Users:')
// console.log({...sendFriends})
// return sendFriends;
}
async findAllPendantRequestsForFriendship(username: string) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
for (const friend of friendship) {
console.log("FRIENDSHIP : " + friend);
partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status});
}
console.log("Pendant requests : " + partialFriendship);
return partialFriendship;
}
async findAllReceivedRequestsForFriendship(username: string) {
async findOneBlocked(friendshipId: number, userId: number) {
// const friendship = await this.friendshipRepository.findOneBy({ id: friendshipId, sender.id: userId, status: FriendshipStatus.BLOCKED });
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.receiverUsername = :addressee', { addressee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
for (const friend of friendship) {
partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status});
}
return partialFriendship;
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.id = :id', { id: friendshipId })
.andWhere('sender.id = :requester', { requester: userId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.getOne();
if (!friendship)
throw new HttpException(`The requested blocked not found.`, HttpStatus.NOT_FOUND);
// return friendship;
return new SendableFriendship(friendship);
}
async create(createFriendshipDto: CreateFriendshipDto, creator : User) : Promise <Partial<Friendship>> {
async findOneBlockedByUsername(blockedUsername : string, userId : number) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('sender.id = :senderId', {senderId : userId})
.andWhere('receiver.username = :friendUsername', {friendUsername : blockedUsername})
.andWhere('friendship.status = :status ', {status : FriendshipStatus.BLOCKED})
.getOne()
if (!friendship) {
throw new HttpException(`The requested blocked not found.`, HttpStatus.NOT_FOUND);
}
return new SendableFriendship(friendship);
}
async findAllBlockedFriends(userId: number) {
const friendships : Friendship[] = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('sender.id = :requestee', { requestee: userId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.getMany();
// let partialFriendship : Partial<Friendship>[] = [];
// for (const friendship of friendships) {
// partialFriendship.push({id: friendship.id, date: friendship.date, senderUsername: friendship.senderUsername, receiverUsername: friendship.receiverUsername, status: friendship.status});
// }
console.log('friendship.service findAllBlockedFriends, friendships:')
console.log({...friendships})
console.log('friendship.service findAllBlockedFriends, partial friendship:')
// console.log({...partialFriendship})
// return partialFriendship;
// return friendships;
let sendFrienships: SendableFriendship[] = []
for (const friendship of friendships) {
sendFrienships.push(new SendableFriendship(friendship));
}
// return new SendableFriendship(friendship);
return sendFrienships;
}
async findAllPendantRequestsForFriendship(userId: number) {
const friendships = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('sender.id = :requestee', { requestee: userId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
console.log('friendships services pendant friendships:')
console.log({...friendships})
let sendFrienships: SendableFriendship[] = []
for (const friendship of friendships) {
sendFrienships.push(new SendableFriendship(friendship));
}
return sendFrienships;
}
async findAllReceivedRequestsForFriendship(userId: number) {
const friendships = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('receiver.id = :addressee', { addressee: userId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
console.log('friendship service received requests')
console.log({...friendships})
let sendFrienships: SendableFriendship[] = []
for (const friendship of friendships) {
sendFrienships.push(new SendableFriendship(friendship));
}
return sendFrienships;
}
// this is no longer the right return
// async create(createFriendshipDto: CreateFriendshipDto, creator : User) : Promise <Partial<Friendship>> {
async create(createFriendshipDto: CreateFriendshipDto, creator : User) {
console.log("DTO : \n")
console.log({...createFriendshipDto})
// These throws don't seem to work...
const receiver = await this.userRepository.findOneBy({username: createFriendshipDto.receiverUsername});
// console.log('receiver: ')
// console.log({...receiver})
if (!receiver)
throw new HttpException(`The addressee does not exist.`, HttpStatus.NOT_FOUND);
if (createFriendshipDto.status !== FriendshipStatus.REQUESTED && createFriendshipDto.status !== FriendshipStatus.BLOCKED)
throw new HttpException(`The status is not valid.`, HttpStatus.NOT_FOUND);
const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver });
// const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver });
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('sender.id = :senderId', {senderId: creator.id})
.andWhere('receiver.id = :receiverId', {receiverId: receiver.id})
.getOne();
console.log('friendship.service create, friendship: \n\n\n')
// console.log({...friendship})
if (friendship) {
console.log('there is already a friend request')
if (friendship.status && friendship.status === FriendshipStatus.ACCEPTED)
throw new HttpException(`The friendship request has already been accepted.`, HttpStatus.OK);
else if (friendship.status && friendship.status === FriendshipStatus.REQUESTED)
@@ -103,99 +277,186 @@ export class FriendshipService {
else if (friendship.status && friendship.status === FriendshipStatus.DECLINED)
throw new HttpException(`The request has been declined.`, HttpStatus.OK);
}
console.log('friendship.service create, we are still saving a new friendship')
const newFriendship = new Friendship();
newFriendship.sender = creator;
newFriendship.senderUsername = creator.username;
// newFriendship.senderUsername = creator.username;
// newFriendship.senderId = creator.id;
newFriendship.receiver = receiver;
newFriendship.receiverUsername = receiver.username;
// newFriendship.receiverUsername = receiver.username;
// newFriendship.receiverId = receiver.id;
newFriendship.status = createFriendshipDto.status;
const savedFriendship = this.friendshipRepository.save(newFriendship);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
console.log({...partialFriendship})
return partialFriendship;
const savedFriendship = await this.friendshipRepository.save(newFriendship);
// const partialFriendship : Partial<Friendship> = {
// id : (await savedFriendship).id,
// date : (await savedFriendship).date,
// receiverUsername: (await savedFriendship).receiverUsername,
// receiverId: (await savedFriendship).receiverId,
// status : (await savedFriendship).status
// }
// console.log('friendship.service create friendship, partial friendship')
// console.log({...partialFriendship})
// console.log('friendship.service create friendship, NEW friendship')
// console.log({...newFriendship})
// console.log('friendship.service create friendship, SAVED friendship')
// console.log({...savedFriendship})
// return partialFriendship;
return new SendableFriendship(savedFriendship);
}
async acceptFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
async acceptFriendship(relationshipId: number, user: User) {
// const relation = await this.friendshipRepository.findOneBy({id: relationshipId });
const relation = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.id = :friendshipId', { friendshipId: relationshipId })
.getOne();
console.log('.service accept friendship')
console.log({...relation})
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
}
relation.status = FriendshipStatus.ACCEPTED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship;
const savedFriendship = await this.friendshipRepository.save(relation);
// const partialFriendship : Partial<Friendship> = {
// id : (await savedFriendship).id,
// date : (await savedFriendship).date,
// receiverUsername: (await savedFriendship).receiverUsername,
// receiverId: (await savedFriendship).receiverId,
// status : (await savedFriendship).status
// }
// console.log('.service accept friendship END')
// console.log({...partialFriendship})
// return partialFriendship;
return new SendableFriendship(savedFriendship);
}
async declineFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
async declineFriendship(relationshipId: number, user: User) {
const relation = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.id = :friendshipId', { friendshipId: relationshipId })
.getOne();
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
throw new HttpException(`You can't decline your own request.`, HttpStatus.NOT_FOUND);
}
relation.status = FriendshipStatus.DECLINED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship
const savedFriendship = await this.friendshipRepository.save(relation);
return new SendableFriendship(savedFriendship);
}
async blockFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
async blockFriendship(relationshipId: number, user: User) {
const relation = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.id = :friendshipId', { friendshipId: relationshipId })
.getOne();
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
// do i need to check if they've already been blocked?
if (relation.receiver.id === user.id) {
// throw new HttpException(`You can't block yourself.`, HttpStatus.NOT_FOUND);
console.log('friendship.service blockFriendship trying to delete and recreate a friendship with block')
console.log({...relation})
// const newFriendshipDto = new CreateFriendshipDto(relation[0].receiver, FriendshipStatus.BLOCKED)
// const newFriendshipDto = new CreateFriendshipDto({"receiverUsername": relation[0].receiver, "status": "R"})
// we create a new one where you are the sender
const newFriendshipDto = {"receiverUsername": relation.sender.username, "receiverId": relation.sender.id, "status": FriendshipStatus.BLOCKED};
// can't do it this way cuz READONLY
// const newFriendshipDto = new CreateFriendshipDto();
// newFriendshipDto.receiverUsername = relation[0].sender.username;
// newFriendshipDto.status = FriendshipStatus.BLOCKED;
// we delete that relation
await this.removeFriendship(relationshipId, user);
// we set it to blocked like we do below...
return await this.create(newFriendshipDto, user);
} else {
relation.status = FriendshipStatus.BLOCKED;
const savedFriendship = await this.friendshipRepository.save(relation);
// const partialFriendship : Partial<Friendship> = {
// id : (await savedFriendship).id,
// date : (await savedFriendship).date,
// receiverUsername: (await savedFriendship).receiverUsername,
// receiverId: (await savedFriendship).receiverId,
// status : (await savedFriendship).status
// }
// return partialFriendship
return new SendableFriendship(savedFriendship);
}
relation.status = FriendshipStatus.BLOCKED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship
}
async removeFriendship(relationshipId: string, user : User) {
const friendship = await this.friendshipRepository.findOneBy({ id: +relationshipId });
if (!friendship)
throw new HttpException(`Your friend could not be deleted.`, HttpStatus.NOT_FOUND);
if (friendship.sender.id !== user.id || friendship.receiver.id !== user.id) {
throw new HttpException(`You can't do that.`, HttpStatus.FORBIDDEN);
}
return this.friendshipRepository.remove(friendship);
}
async findIfUserIsBlockedOrHasBlocked(userConnectedId: string, userToFindId: string) {
console.log("finding if user is blocked")
async removeFriendship(relationshipId: number, user : User) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: userConnectedId })
.orWhere('friendship.senderUsername = :requesteeBis', { requesteeBis: userToFindId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where('friendship.id = :friendshipId', { friendshipId: relationshipId })
.getOne();
console.log('deleting a friendship .service')
console.log({...friendship})
console.log('who is the user')
console.log({...user})
if (!friendship)
throw new HttpException(`Your friend could not be deleted.`, HttpStatus.NOT_FOUND);
if (friendship.sender.id !== user.id && friendship.receiver.id !== user.id) {
throw new HttpException(`You can't do that.`, HttpStatus.FORBIDDEN);
}
console.log('.service deleted a friendship')
return this.friendshipRepository.remove(friendship);
// what is the return here? am i getting something right?
}
// ok for some reason this isn't working...
async findIfUserIsBlockedOrHasBlocked(userConnectedId: number, userToFindId: number) {
console.log("finding if user is blocked")
console.log('user connected: ' + userConnectedId)
console.log('user to find: ' + userToFindId)
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.leftJoinAndSelect('friendship.sender', 'sender')
.leftJoinAndSelect('friendship.receiver', 'receiver')
.where(
new Brackets((qb) => {
qb.where(
new Brackets((subAQb) => {
subAQb.where('sender.id = :senderId', { senderId: userConnectedId})
.andWhere('receiver.id = :receiverId', { receiverId: userToFindId})
})
)
.orWhere(
new Brackets((subBQb) => {
subBQb.where('sender.id = :senderId2', {senderId2 : userToFindId})
.andWhere('receiver.id = :receiverId2', {receiverId2 : userConnectedId})
})
)
}),
)
.andWhere('friendship.status = :status', {status : FriendshipStatus.BLOCKED})
.getOne()
console.log('printing friendship queried')
console.log({...friendship})
if (friendship) {
console.log('we are blocked in friendship.service')
return true;
}
console.log('we are not blocked in friendship service')
return false;
}
}
}

View File

@@ -0,0 +1,24 @@
import { Friendship, FriendshipStatus } from "./entities/friendship.entity";
// Ok i don't really know what i'm doing but i want a thing that is typeset that i can use to send info back to the Front when they create a friendship or ask for a friendship
// Ok it doesn't seem like i really need an interface, that just enfoces the types
// export interface SendableFriendship {
export class SendableFriendship {
id: number;
date: Date;
senderUsername: string;
receiverUsername: string;
status: FriendshipStatus;
// if my constructor is here won't it get sent all over the place too?
constructor(friendship: Friendship) {
this.id = friendship.id;
this.date = friendship.date
this.senderUsername = friendship.sender.username;
this.receiverUsername = friendship.receiver.username;
this.status = friendship.status;
};
}

View File

@@ -51,7 +51,7 @@ export class GameService {
const partialUser : Partial<User>[] = []
for (const user of users)
{
if (await this.friendShipService.findIfUserIsBlockedOrHasBlocked(currentUser.id.toString(), user.id.toString()) === false)
if (await this.friendShipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, user.id) === false)
partialUser.push({username : user.username, stats : user.stats })
}
console.log(...partialUser)
@@ -92,7 +92,7 @@ export class GameService {
}
if (grantTicketDto.isGameIsWithInvitation === true)
{
const secondUser : Partial<User> = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername)
const secondUser : Partial<User> = await this.userService.findOne(grantTicketDto.playerTwoUsername)
if (!secondUser || secondUser.username === user.username)
return res.status(HttpStatus.NOT_FOUND).json({message : "User not found OR you want to play with yourself."});
const encryptedTextToReturn = await this.encryptToken(user.username + '_' + secondUser.username + '_'

View File

@@ -0,0 +1,18 @@
import { User } from "./entities/user.entity";
import { UserStats } from "./entities/userStat.entities";
export class SendableUser {
username: string;
image_url : string;
status: string;
stats: UserStats;
// if my constructor is here won't it get sent all over the place too?
constructor(user: User) {
this.username = user.username;
this.image_url = user.image_url;
this.status = user.status;
this.stats = user.stats;
};
}

View File

@@ -19,48 +19,67 @@ export class UsersController {
constructor(private readonly usersService: UsersService) {}
// par exemple dans postamn ou insomnia http://localhost:3000/users?limit=10&offset=20
// GET http://transcendance:8080/user/all
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('all')
findAll(@Query() paginationquery : PaginationQueryDto) {
//const { limit, offset } = query;
return this.usersService.findAll(paginationquery);
findAll(@Req() req) {
const user : User = req.user;
return this.usersService.findAll(user);
}
////////////////////////////////////////////////////////
///////////////////////// RUD //////////////////////////
////////////////////////////////////////////////////////
/**
* On ne fait de création via une route
* car un utilisateur est crée à la première connexion avec l'Oauth de 42.
*/
// actually fucking useless now...
// similar to @Get('myfriends/:friendUsername') but doesn't return a friendship just returns the user profile
// GET http://transcendance:8080/user?username=NomDuUser
// @UseGuards(AuthenticateGuard)
// @UseGuards(TwoFactorGuard)
// @Get()
// findOne(@Query('id') toFindId: number, @Req() req) {
// if (toFindId === undefined) {
// console.log("Backend Getting current user");
// return this.usersService.findOne(req.user.id);
// } else {
// const user : User = req.user;
// console.log('we have a query: ' + toFindId)
// return this.usersService.findOneById(user.id, toFindId);
// }
// }
// GET http://transcendance:8080/user
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get()
findOne(@Query('username') username: string, @Req() req) {
if (username === undefined) {
return this.usersService.findOne(req.user.id);
} else {
const user : User = req.user;
return this.usersService.findOneByUsername(user.id.toString(),username);
}
findOne(@Query('username') usernameToFind: string, @Req() req) {
console.log('users service findOne usernameToFind:')
console.log(usernameToFind)
console.log('users service findOne my Username:')
console.log(req.user.username)
if (usernameToFind === undefined)
return this.usersService.findOne(req.user.username);
else
return this.usersService.findOne(usernameToFind);
}
// GET http://transcendance:8080/user?username=NomDuUser
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('search')
findOneByUsername(@Query('username') username: string, @Req() req) {
const user : User = req.user;
return this.usersService.findOneByUsername(user.id.toString(),username);
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('stats')
getStats(@Req() request) {
return this.usersService.getStats(request.user.id);
}
// also seems useless...
// GET http://transcendance:8080/user/stats
// @UseGuards(AuthenticateGuard)
// @UseGuards(TwoFactorGuard)
// @Get('stats')
// getStats(@Req() request) {
// return this.usersService.getStats(request.user.id);
// }
// PATCH http://transcendance:8080/user
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Patch()
@@ -76,6 +95,7 @@ export class UsersController {
response.status(200).send("OK")
}
// DELETE http://transcendance:8080/user
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Delete()
@@ -83,6 +103,7 @@ export class UsersController {
return this.usersService.remove(req.user.id);
}
// POST http://transcendance:8080/user/avatar
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('avatar')
@@ -97,6 +118,7 @@ export class UsersController {
return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."});
}
// GET http://transcendance:8080/user/avatar
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('avatar')

View File

@@ -1,7 +1,7 @@
import { HttpException, HttpStatus, Injectable, NotFoundException, } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';
import { Repository, Not } from 'typeorm';
import { CreateUsersDto } from './dto/create-users.dto';
import { UpdateUsersDto } from './dto/update-users.dto';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
@@ -29,15 +29,15 @@ export class UsersService {
return user;
}
async findOne(id: string) {
console.log(`FIND ONE USER SERVICE Find user ${id}`);
async findOne(username: string) {
console.log(`FIND ONE USER SERVICE Find user ${username}`);
const user = await this.userRepository.createQueryBuilder('user')
.leftJoinAndSelect('user.stats', 'stats')
.where('user.id = :id', { id: +id })
.where('user.username = :username', { username: username })
.getOne();
if (!user)
throw new NotFoundException(`The requested user not found.`);
console.log(`FIND ONE USER SERVICE The requested user found.` + user.username
console.log(`FIND ONE USER SERVICE The requested user found. ` + user.username + " "
+ user.stats.id + user.stats.winGame + user.stats.loseGame + user.stats.drawGame + user.stats.totalGame);
const partialUser : Partial<User> = {
username: user.username,
@@ -50,6 +50,10 @@ export class UsersService {
return partialUser;
}
/***** THIS IS THE THING I REALLY NEED TO FIX!!!!!!! *****/
// Ok this gets called in the Authenitcation Service, but like i was still able to make a username === someone else's
async isUsernameExists(usernameToSearch: string): Promise<boolean> {
const user = await this.userRepository.findOneBy({username : usernameToSearch});
if (!user)
@@ -57,38 +61,51 @@ export class UsersService {
return true;
}
async findOneByUsername(userConnectedId : string, usernameToFind: string) {
const userToFind : User = await this.userRepository.createQueryBuilder('user')
.leftJoinAndSelect('user.stats', 'stats')
.where('user.username = :username', { username: usernameToFind })
.getOne();
console.log('USERNAME OF FOUND USER : ' + userToFind.username);
// console.log({...user})
// you can't do that, you need to do user === undefined
// if (user === undefined)
if (!userToFind)
throw new HttpException(`The user could not be found 1.`,HttpStatus.NOT_FOUND);
if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(userConnectedId, userToFind.id.toString())) {
console.log('we are blocked in user.service')
throw new HttpException(`The user could not be found 2.`,HttpStatus.NOT_FOUND);
async findAll(currentUser: User) {
// const otherUsers = await this.userRepository.find({where: {id: Not(+currentUser.id)}, order: {username: "ASC"}, skip: offset, take: limit,});
const otherUsers = await this.userRepository.find({where: {id: Not(+currentUser.id)}, order: {username: "ASC"}});
let partialUsers : Partial<User>[] = [];
for (const otherUser of otherUsers) {
console.log('other user: ')
console.log({...otherUser})
let tmp = await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id);
console.log('user.services findIF Blocked... : ')
console.log(tmp)
if (tmp === false) {
// if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id) === false) {
partialUsers.push({username: otherUser.username, image_url: otherUser.image_url, status: otherUser.status, stats: otherUser.stats});
}
}
const partialUser : Partial<User> = {
username: userToFind.username,
image_url: userToFind.image_url,
status: userToFind.status,
stats: userToFind.stats,
};
return partialUser;
console.log('user.services findAll, partialUsers:')
console.log({...partialUsers})
return partialUsers;
}
// Example : http://localhost:3000/users?limit=10&offset=20
findAll(paginationquery : PaginationQueryDto) {
const { limit, offset } = paginationquery;
return this.userRepository.find({
skip: offset,
take: limit,
});
}
// async findAbsolutelyAll() {
// // const otherUsers = await this.userRepository.find({where: {id: Not(+currentUser.id)}, order: {username: "ASC"}, skip: offset, take: limit,});
// const otherUsers = await this.userRepository.find({order: {username: "ASC"}});
// let partialUsers : Partial<User>[] = [];
// for (const otherUser of otherUsers) {
// console.log('other user: ')
// console.log({...otherUser})
// let tmp = await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id);
// console.log('user.services findIF Blocked... : ')
// console.log(tmp)
// if (tmp === false) {
// // if (await this.friendshipService.findIfUserIsBlockedOrHasBlocked(currentUser.id, otherUser.id) === false) {
// partialUsers.push({username: otherUser.username, image_url: otherUser.image_url, status: otherUser.status, stats: otherUser.stats});
// }
// }
// console.log('user.services findAll, partialUsers:')
// console.log({...partialUsers})
// return partialUsers;
// }
async create(createUserDto: CreateUsersDto) {
if (await this.userRepository.findOneBy({fortyTwoId: createUserDto.fortyTwoId}))
@@ -100,28 +117,28 @@ export class UsersService {
return this.userRepository.save(user);
}
async update(id: string, updateUserDto: UpdateUsersDto) {
console.log(`Update user ${id} with ${updateUserDto.isEnabledTwoFactorAuth}`);
async update(id: number, updateUserDto: UpdateUsersDto) {
// console.log(`Update user ${id} with ${updateUserDto.isEnabledTwoFactorAuth}`);
const user = await this.userRepository.preload(
{id: +id,
{id: id,
...updateUserDto});
if (!user)
throw new HttpException(`The user could not be updated.`,HttpStatus.NOT_FOUND);
return this.userRepository.save(user);
}
async remove(id: string) {
const user = await this.userRepository.findOneBy({id: +id});
async remove(id: number) {
const user = await this.userRepository.findOneBy({id: id});
if (!user)
throw new HttpException(`The user could not be deleted.`,HttpStatus.NOT_FOUND);
return this.userRepository.remove(user);
}
async enableTwoFactorAuth(id: string) {
async enableTwoFactorAuth(id: number) {
return this.userRepository.update(id, {isEnabledTwoFactorAuth: true});
}
async authenticateUserWith2FA(id: string) {
async authenticateUserWith2FA(id: number) {
return this.userRepository.update(id, { isTwoFactorAuthenticated: true})
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,6 @@
import { push } from "svelte-spa-router";
import { onMount } from 'svelte';
let user;
onMount(async () => {

View File

@@ -23,7 +23,7 @@
<div class="outer">
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
{#if user !== undefined}
<GenerateUserDisplay {user} primary={true}/>
<GenerateUserDisplay user={user} primary={true}/>
{:else}
<!-- might be unnecessary since you can't access the page without fetching the user -->
<h2>Sorry</h2>

View File

@@ -1,217 +1,356 @@
<script lang="ts">
import { onMount } from "svelte";
import { binding_callbacks } from "svelte/internal";
import { binding_callbacks, empty } from "svelte/internal"; // WTF is this?
import Button from "../../pieces/Button.svelte";
import DisplayAUser from "../../pieces/DisplayAUser.svelte";
import Tabs from "../../pieces/Tabs.svelte";
let errors = {friendRequest: '',};
let set = {friendUsername: '', friendId: Number}
let set = {friendUsername: ''}
let user;
let allUsers;
let myFriends;
let myFriendships;
let requestsMade, requestsRecieved;
let userBeingViewed;
let blockedUsers;
let usernameBeingViewed;
let friendshipStatusFull; // id, date, senderUsername, reveiverUsername, status
/**** Layout variables ****/
let tabItems: string[] = ['All Users', 'My Friends', 'Friend Requests', 'Blocked Users']
let activeTabItem: string = 'All Users';
onMount( async() => {
// DO I ACTUALLY NEED TO ON MOUNT ALL THIS STUFF?
// ALSO I COULD JUST USE THE FUNCITONS I MADE...
// yea no idea what
// i mean do i fetch user? i will for now
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() );
fetchAll();
// ok this shit works!
// const interval = setInterval(() => {
// fetchAll();
// }, 1000);
myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( (x) => x.json() );
// return () => clearInterval(interval);
});
const fetchAll = async() => {
// no need to await i think it can load in the background
fetchAllUsers();
fetchMyFriendships();
fetchRequestsMade();
fetchRequestsReceived();
fetchBlockedUsers();
}
/***** Fetch basic things *****/
const fetchAllUsers = async() => {
allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() );
console.log('got all users ')
console.log({...allUsers})
};
// it's more like fetch friendships
// then i need to extract the users
const fetchMyFriendships = async() => {
myFriendships = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( x => x.json() );
console.log('got my friends ')
console.log({...myFriendships})
};
const fetchRequestsMade = async() => {
requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() );
console.log('got requests made ')
console.log({...requestsMade})
};
const fetchRequestsReceived = async() => {
requestsRecieved = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/received`)
.then( x => x.json() );
allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() );
})
const displayAllUsers = async() => {
allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() );
// console.log('got all users ' + allUsers)
console.log('got requests received ')
console.log({...requestsRecieved})
};
const displayAllFriends = async() => {
myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
const fetchBlockedUsers = async() => {
blockedUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/blocked`)
.then( x => x.json() );
// console.log('got all friends ' + allFriends)
console.log('got blocked users, is it empty?')
console.log({...blockedUsers})
console.log(Object.keys(blockedUsers))
};
/**** END OF MAIN FETCH ****/
// returns everything but BLOCKED
const fetchFriendshipFull = async(aUsername) => {
console.log('fetch friendship from a username')
console.log(aUsername)
friendshipStatusFull = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends?username=${aUsername}`)
.then( x => x.json());
console.log({...friendshipStatusFull})
};
const displayRequestsMade = async() => {
requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() );
// console.log('got requests made ' + requestsMade)
};
let sentFriendRequest;
const sendFriendRequest = async(potentialFriendUsername) => {
set.friendUsername = '';
errors.friendRequest = '';
let valid = false;
if (potentialFriendUsername === user.username) {
errors.friendRequest = "You can't friend yourself."
valid = false;
} else {
set.friendUsername = potentialFriendUsername;
valid = true;
}
if (valid) {
sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`, {
method : "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
"receiverUsername": set.friendUsername,
"status": "R"
})
const sendFriendRequest = async(aUsername) => {
console.log('sending a friend request')
console.log(aUsername)
const resp = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, {
method : "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
"receiverUsername": aUsername,
"status": "R"
})
.then( x => x.json())
})
.then( x => x.json())
// .catch( x => console.log({...x}))
// "status": "A"
console.log({...resp})
fetchFriendshipFull(aUsername);
};
const viewAUser = async(aUsername) => {
console.log('Profile Friend updating userBeingViewed')
usernameBeingViewed = aUsername;
// friendshipStatusFull = undefined;
// id, date, senderUsername, reveiverUsername, status
await fetchFriendshipFull(aUsername);
console.log('Friendship Status Full')
console.log({...friendshipStatusFull})
};
const acceptFriendRequest = async(relationshipId) => {
console.log('accept friend request')
const resp = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations/${relationshipId}/accept`, {
method: "PATCH"})
.then( x => x.json());
// maybe not the most robust things, not super reusable cuz it depends on outside vars but works for now...
console.log('accepted friend request, now response')
console.log({...resp})
await fetchFriendshipFull(usernameBeingViewed);
// will this make it reload? C'est un peu bourain... do i even need it?
activeTabItem = activeTabItem;
};
const declineFriendRequest = async(relationshipId) => {
console.log('decline friend request')
const resp = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations/${relationshipId}/decline`, {
method: "PATCH"})
.then( x => x.json());
// maybe not the most robust things, not super reusable cuz it depends on outside vars but works for now...
console.log('declined friend request, now response')
console.log({...resp})
await fetchFriendshipFull(usernameBeingViewed);
};
const unfriend = async(relationshipId) => {
console.log('Unfriend')
const resp = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations/${relationshipId}`, {
method: "DELETE"})
.then( x => x.json());
// friendshipStatusFull = undefined;
// OR
await fetchFriendshipFull(usernameBeingViewed);
if (Object.keys(friendshipStatusFull).length === 0)
friendshipStatusFull = undefined;
// will this make it reload? C'est un peu bourain... do i even need it?
activeTabItem = activeTabItem;
};
const blockANonFriendUser = async(aUsername) => {
console.log('Block a non friend user, their username')
console.log(aUsername)
sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations`, {
method : "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
"receiverUsername": aUsername,
"status": "B"
})
})
.then( x => x.json())
await fetchBlockedUsers();
await fetchAllUsers();
usernameBeingViewed = undefined;
friendshipStatusFull = undefined;
// will this make it reload?
activeTabItem = activeTabItem;
};
const blockAFriend = async(relationshipId) => {
console.log('blocking a friend, the relationshipID')
console.log(relationshipId)
const resp = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/relations/${relationshipId}/block`, {method: "PATCH"})
.then( x => x.json() );
console.log('blocked a user response')
console.log({...resp})
await fetchBlockedUsers();
await fetchAllUsers();
usernameBeingViewed = undefined;
friendshipStatusFull = undefined;
// will this make it reload?
activeTabItem = activeTabItem;
};
const unblockAUser = async(relationshipId) => {
// it's basically the same as unfriending someone cuz unfriending them means the relationship is deleted
await unfriend(relationshipId);
};
const switchTab = async(e) => {
activeTabItem = e.detail;
if (activeTabItem === 'All Users') {
await fetchAllUsers();
} else if (activeTabItem === 'My Friends') {
await fetchMyFriendships();
} else if (activeTabItem === 'Friend Requests') {
await fetchRequestsReceived();
} else if (activeTabItem === 'Blocked Users') {
await fetchBlockedUsers();
console.log('blocked users: ')
console.log({...blockedUsers})
}
};
// let sendUsername;
const viewAUser = async(aUser) => {
userBeingViewed = aUser;
// sendUsername = userBeingViewed.username;
// prolly like fetch if you're friends or not?
// GET `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif
// doesn't have a better option
// like i want this thing to return the Friendship ID ideally
};
const blockAUser = async(friendshipId) => {
};
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="top-grid">
<div class="all-users-sidebar">
<h3>All Users</h3>
{#if allUsers === undefined}
<div class="error">Failed to load all users</div>
{:else}
<!-- let tabItems: string[] = ['All Users', 'My Friends', 'Friend Requests']
let activeTabItem: string = 'All Users'; -->
<!-- maybe add numbers at the botton? like for how many of each there are? -->
<div class="sidebar-list">
<Tabs items={tabItems} activeItem={activeTabItem} size="small" on:tabChange={switchTab}/>
{#if activeTabItem === 'All Users' && allUsers !== undefined}
<h3>{activeTabItem}</h3>
<!-- problem, i can't use user.id since Cherif doesn't want to expost that to the front...
is there something else i could use? -->
<!-- add a thing so it doesn't display the current user just all the other users -->
{#if Object.keys(allUsers).length === 0}
<div class="tip">You are alone on this platform...</div>
{/if}
<!-- does this work? -->
<!-- {#each allUsers as aUser (aUser.username)} -->
{#each allUsers as aUser }
<!-- <div class="a-user" on:click={() => displayAUser(aUser.username)}>{aUser.username}</div> -->
<div class="a-user" on:click={() => viewAUser(aUser)}>{aUser.username}</div>
<!-- {#each allUsers as aUser (aUser.id)} -->
{#each allUsers as aUser}
<div class="sidebar-item" on:click={() => viewAUser(aUser.username)}>{aUser.username}</div>
<!-- i could make an indicator component? like green for connected or something?
i could use words but color them?
i could make it so if they're in a game -->
<div class="status a-user">{aUser.status}</div>
<div class="status sidebar-item">{aUser.status}</div>
<br>
{/each}
{:else if activeTabItem === 'My Friends' && myFriendships !== undefined}
<h3>{activeTabItem}</h3>
{#if Object.keys(myFriendships).length === 0}
<div class="tip">You don't have any Friends... Yet!</div>
{/if}
<!-- {#each myFriends as aUser (aUser.id)} -->
{#each myFriendships as aFriendship}
{#if aFriendship.senderUsername !== user.username}
<div class="sidebar-item" on:click={() => viewAUser(aFriendship.senderUsername)}>{aFriendship.senderUsername}</div>
{:else if aFriendship.receiverUsername !== user.username}
<div class="sidebar-item" on:click={() => viewAUser(aFriendship.receiverUsername)}>{aFriendship.receiverUsername}</div>
{/if}
<br>
{/each}
{:else if activeTabItem === 'Friend Requests' && requestsRecieved !== undefined}
<h3>{activeTabItem}</h3>
{#if Object.keys(requestsRecieved).length === 0}
<div class="tip">You don't have any Friend Requests</div>
{/if}
<!-- {#each requestsRecieved as aUser (aUser.id)} -->
{#each requestsRecieved as aUser}
<div class="sidebar-item" on:click={() => viewAUser(aUser.senderUsername)}>{aUser.senderUsername}</div>
<div class="status sidebar-item">{aUser.status}</div>
<br>
{/each}
{:else if activeTabItem === 'Blocked Users' && blockedUsers !== undefined}
<h3>{activeTabItem}</h3>
<!-- seems a little excessive... maybe a lighter way of doing this? doesn't seem like it, i hate it but at least only happens sometimes.default... -->
{#if Object.keys(blockedUsers).length === 0}
<div class="tip">You have not Blocked any Users</div>
{/if}
<!-- {#each blockedUsers as aUser (aUser.id)} -->
{#each blockedUsers as aUser}
<div class="sidebar-item" on:click={() => viewAUser(aUser.receiverUsername)}>{aUser.receiverUsername}</div>
<div class="status sidebar-item">{aUser.status}</div>
<br>
{/each}
{/if}
</div>
<div class="main-display">
{#if usernameBeingViewed !== undefined}
<!-- <DisplayAUser aUsername={usernameBeingViewed}/> -->
<DisplayAUser aUsername={usernameBeingViewed}/>
<h1>Main Display</h1>
<!-- use an #await here too? -->
<!-- you can do better, like an on load sort of thing -->
<!-- {#if userBeingViewed !== undefined && userBeingViewed === tmpUserBeingViewed} -->
<!-- {#if userBeingViewed !== undefined} -->
{#if userBeingViewed}
<div>{userBeingViewed.username}</div>
<DisplayAUser aUsername={userBeingViewed.username}/>
<!-- <DisplayAUser aUsername={sendUsername}/> -->
<Button type="secondary" on:click={() => sendFriendRequest(userBeingViewed.username)}>Add Friend</Button>
<!-- {#if user not blocked}
<Button on:click={() => blockAUser(userBeingViewed.username)}>Add Friend</Button>
does it have to be friendship IDs? can't i just use username?
i mean i guess friendship ID is more secure, and also easier in the back
but if i'm using friendshi ID i need a good way of getting them
{/if} -->
<!-- {:else if userBeingViewed !== undefined} -->
<div class="buttons-area">
{#if friendshipStatusFull && friendshipStatusFull.id}
{#if friendshipStatusFull.status === 'R'}
{#if friendshipStatusFull.senderUsername === user.username}
<div class="tile">Friend Request Sent</div>
{:else}
<!-- <Button type="secondary" on:click={() => acceptFriendRequest(usernameBeingViewed)}>Unfriend</Button> -->
<Button type="secondary" on:click={() => acceptFriendRequest(friendshipStatusFull.id)}>Accept Friend Request</Button>
<Button on:click={() => declineFriendRequest(friendshipStatusFull.id)}>Decline Friend Request</Button>
{/if}
<Button on:click={() => blockAFriend(friendshipStatusFull.id)}>Block User</Button>
{:else if friendshipStatusFull.status === 'A'}
<div class="tile">You are Friends</div>
<Button on:click={() => unfriend(friendshipStatusFull.id)}>Unfriend</Button>
<Button on:click={() => blockAFriend(friendshipStatusFull.id)}>Block User</Button>
{:else if friendshipStatusFull.status === 'D'}
{#if friendshipStatusFull.senderUsername === user.username}
<div class="tile">Your friend request was declined, hang in there bud.</div>
{:else}
<div class="tile">You declined the friend request, but you could still change your mind</div>
<Button on:click={() => acceptFriendRequest(friendshipStatusFull.id)}>Accept Friend Request</Button>
{/if}
<Button on:click={() => blockAFriend(friendshipStatusFull.id)}>Block User</Button>
{:else if friendshipStatusFull.status === 'B'}
{#if friendshipStatusFull.senderUsername === user.username}
<Button on:click={() => unblockAUser(friendshipStatusFull.id)}>Unblock User</Button>
{/if}
{/if}
{:else}
<Button type="secondary" on:click={() => sendFriendRequest(usernameBeingViewed)}>Add Friend</Button>
<Button on:click={() => blockANonFriendUser(usernameBeingViewed)}>Block User</Button>
{/if}
<!-- <Button type="secondary" on:click={() => sendFriendRequest(usernameBeingViewed)}>Add Friend</Button> -->
</div>
{:else}
<div class="placeholder">
<h1>Click on a user!</h1>
<h4>You'll see them displayed here</h4>
</div>
{/if}
<!-- {#await userBeingViewed}
<p>... waiting</p>
{:then}
<div>{userBeingViewed.username}</div>
<DisplayAUser aUsername={userBeingViewed.username}/>
<Button type="secondary" on:click={() => sendFriendRequest(userBeingViewed.username)}>Add Friend</Button>
{:catch}
<p>No user to view yet</p>
{/await} -->
<!-- {#if user not blocked}
<Button on:click={() => blockAUser(userBeingViewed.username)}>Add Friend</Button>
does it have to be friendship IDs? can't i just use username?
i mean i guess friendship ID is more secure, and also easier in the back
but if i'm using friendshi ID i need a good way of getting them
{/if} -->
<!-- {:else if userBeingViewed !== undefined} -->
<!-- <Button on:click={displayAllUsers}>Get All Users</Button>
{#if allUsers !== undefined}
{#each allUsers as user}
<div>{user.username}</div>
{/each}
{/if}
<br> -->
<!-- <Button on:click={displayMyFriends}>Get All My Friends</Button>
{#if myFriends !== undefined}
<div>{myFriends}</div>
{#each myFriends as friend}
<div>{friend}{friend.username}</div>
{/each}
{/if} -->
<!-- <br> <br> -->
<!-- here i want to list all the requests you and have an accept and a decline button -->
<!-- {#each requestsRecieved as request} -->
<!-- <br> <br> -->
<!-- I want to list all the requests made by this user -->
<!-- <Button on:click={displayRequestsMade}>Display Requests Made</Button>
{#if requestsMade !== undefined}
{#each requestsMade as requestMade}
<div>{requestMade}</div>
{/each}
{/if} -->
</div>
</div>
@@ -227,12 +366,12 @@
/* margin: 0; */
}
div.all-users-sidebar{
div.sidebar-list{
grid-column: 1 / span 2;
background: white;
}
div.a-user{
div.sidebar-item{
/* yea i mean that seems fine... */
display: inline-block;
/* somehting about the buttons too, smaller ? */
@@ -243,7 +382,7 @@
}
/* selector attributes to get only divs with .a-user */
/* you gotta be careful with Svelte cuz it tacks classes on to the end of basically all elems! */
div[class^="a-user"]:hover{
div[class^="sidebar-item"]:hover{
text-decoration: underline;
font-weight: bold;
cursor: pointer;
@@ -253,6 +392,21 @@
grid-column: 3 / span 10;
}
div.placeholder{
color: darkgray;
text-align: center;
}
div.buttons-area{
text-align: center;
}
div.tip{
color: darkgray;
font-size: 0.8em;
font-weight: bold;
}
.error{
font-size: 0.8em;

View File

@@ -1,8 +1,9 @@
<script lang="ts">
import { onMount } from 'svelte';
import { onMount, afterUpdate } from 'svelte';
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
// export let aUsername;
export let aUsername;
let user;
@@ -11,24 +12,35 @@
//`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
})
// sadly created an infinite loop
// afterUpdate( async() => {
// console.log('Display Update aUser username: '+ aUsername)
// // http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
// user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
// .then( (x) => x.json() );
// })
const updateUser = async(updatedUser) => {
console.log('Display Update aUser username: '+ updateUser)
//`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${updateUser}`)
export const updateUser = async() => {
// console.log('Display Update aUser username: '+ aUsername)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
// user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
};
// $: aUsername, updateUser();
$: aUsername, updateUser();
</script>
{#if user !== undefined}
<GenerateUserDisplay bind:user={user} primary={true}/>
<GenerateUserDisplay user={user} primary={true}/>
<!-- <GenerateUserDisplay user={user} primary={true}/> -->
{:else}
<h2>Sorry</h2>
<div>Failed to load user {aUsername}</div>

View File

@@ -21,7 +21,6 @@
}
})
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {

View File

@@ -2,17 +2,19 @@
import { createEventDispatcher } from "svelte";
export let items;
export let activeItem;
export let size = 'medium';
// big, medium, small
const dispatch = createEventDispatcher();
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="tabs">
<div class="tabs" class:size={size}>
<!-- creates a list, can be done other ways -->
<ul>
{#each items as item}
<li on:click={() => dispatch('tabChange', item)}>
<li class={size} on:click={() => dispatch('tabChange', item)}>
<!-- the class active is attributed if the condition is met -->
<div class:active={activeItem === item}>{item}</div>
</li>
@@ -21,8 +23,20 @@
</div>
<style>
.tabs{
/* .tabs{
margin-bottom: 40px;
} */
.tab.big{
margin-bottom: 50px;
/* guessing at size */
}
.tab.medium{
margin-bottom: 40px;
/* the OG size */
}
.tab.small{
margin-bottom: 10px;
/* need it small */
}
ul{
display: flex;
@@ -31,11 +45,28 @@
list-style-type: none;
}
li{
margin: 0 16px;
font-size: 18px;
/* margin: 0 16px; */
/* font-size: 18px; */
color: #555;
cursor: pointer;
}
li.big{
margin: 0 20px;
font-size: 22px;
/* guessing at size */
}
li.medium{
margin: 0 16px;
font-size: 18px;
/* the OG size */
}
li.small{
margin: 8px;
font-size: 10px;
/* need it small */
}
.active{
color: #d91b42;
border-bottom: 2px solid #d91b42;