Skip to content

Commit

Permalink
Feat/user-unique-name (#94)
Browse files Browse the repository at this point in the history
* feat: allow user to use a unique displayname

* feat: add displayName as default identifier on front

* feat: use displayname on leaderboard

* feat: allow user to update name on front

* fix: display name validation freezing auth

* feat: add uploads folder into gitignore

* chore: lint

* feat: remove user avatar from user patch

* fix: rollback chat

---------

Co-authored-by: Victor Wildner <[email protected]>
  • Loading branch information
iaurg and vcwild authored Nov 16, 2023
1 parent f7abf24 commit 1b4960a
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@ postgres/
=======
# Local Uploads
/backend/uploads/*
data
data
2 changes: 2 additions & 0 deletions backend/src/auth/jwt/jwt.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ export class JwtAuthService {

async generateJwt(user: User, mfaAuthenticated = false) {
const payload = this.generatePayload(user, mfaAuthenticated);

const accessToken = this.jwtService.sign(payload, {
expiresIn: this.accessTokenExpiration,
secret: this.configService.get('JWT_SECRET'),
});

const refreshToken = this.jwtService.sign(payload, {
expiresIn: this.refreshTokenExpiration,
secret: this.configService.get('JWT_SECRET'),
Expand Down
4 changes: 2 additions & 2 deletions backend/src/leaderboard/leaderboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class LeaderboardService {
victory: 'desc',
},
select: {
login: true,
displayName: true,
victory: true,
avatar: true,
id: true,
Expand All @@ -27,7 +27,7 @@ export class LeaderboardService {
id: id,
},
select: {
login: true,
displayName: true,
victory: true,
avatar: true,
},
Expand Down
4 changes: 0 additions & 4 deletions backend/src/users/dto/patchUser.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ export class PatchUserDto {
@IsOptional()
displayName?: string;

@IsString()
@IsOptional()
avatar?: string;

@IsBoolean()
@IsOptional()
mfaEnabled?: boolean;
Expand Down
11 changes: 4 additions & 7 deletions backend/src/users/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,17 @@ export class UsersController {
return this.service.create(createUserDto);
}

@Patch(':login')
@Patch()
update(
@Req() request: Request & { user: User },
@Param('login') login: string,
@Body() updateUserDto: PatchUserDto,
) {
const { user } = request;

if (user.login !== login) {
throw new UnauthorizedException(
'You are not authorized to update this user',
);
if (!user.login) {
throw new UnauthorizedException('User not found.');
}

return this.service.update(login, updateUserDto);
return this.service.update(user.login, updateUserDto);
}
}
17 changes: 11 additions & 6 deletions backend/src/users/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateUserDto } from './dto/createUser.dto';
import { UpdateUserDto } from './dto/updateUser.dto';
Expand Down Expand Up @@ -44,17 +44,22 @@ export class UsersService {
}

async update(login: string, updateUserDto: UpdateUserDto) {
if (updateUserDto.displayName) {
const displayName = await this.prisma.user.findFirst({
where: { displayName: updateUserDto.displayName },
});

if (displayName) {
throw new BadRequestException('Display name already taken');
}
}

return await this.prisma.user.update({
where: { login: login },
data: {
displayName: updateUserDto.displayName,
avatar: updateUserDto.avatar,
status: updateUserDto.status,
victory: updateUserDto.victory,
updatedAt: new Date(),
refreshToken: updateUserDto.refreshToken,
mfaSecret: updateUserDto.mfaSecret,
mfaEnabled: updateUserDto.mfaEnabled,
},
});
}
Expand Down
75 changes: 63 additions & 12 deletions frontend/src/components/EditUserModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AuthContext } from "@/contexts/AuthContext";
import { api } from "@/services/apiClient";
import { queryClient } from "@/services/queryClient";
import { Dialog, Transition } from "@headlessui/react";
import { PencilSimple } from "@phosphor-icons/react";
import { Fragment, useContext, useState } from "react";
Expand All @@ -8,6 +9,7 @@ import toast from "react-hot-toast";

export default function EditUserModal() {
const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const { user } = useContext(AuthContext);
const {
register,
Expand All @@ -25,18 +27,45 @@ export default function EditUserModal() {

const onSubmit = async (data: any) => {
// create a new form data and append the data, send to api
const formData = new FormData();
formData.append("file", data.avatar[0]);
if (data.username) {
setIsLoading(true);
await api
.patch("/users", {
displayName: data.username,
})
.then(() => {
toast.success("Nome de usuário atualizado com sucesso!");
queryClient.invalidateQueries(["users"]);
})
.catch((error) => {
toast.error(
`Erro ao atualizar nome de usuário: ${error.response.data.message}`
);
})
.finally(() => {
setIsLoading(false);
setIsOpen(false);
});
}

await api
.post("/avatar-upload", formData)
.then(() => {
toast.success("Avatar atualizado com sucesso!");
setIsOpen(false);
})
.catch(() => {
toast.error("Erro ao atualizar avatar!");
});
if (data.avatar.length > 0) {
setIsLoading(true);
const formData = new FormData();
formData.append("file", data.avatar[0]);

await api
.post("/avatar-upload", formData)
.then(() => {
toast.success("Avatar atualizado com sucesso!");
})
.catch(() => {
toast.error("Erro ao atualizar avatar!");
})
.finally(() => {
setIsLoading(false);
setIsOpen(false);
});
}
};

return (
Expand Down Expand Up @@ -118,8 +147,30 @@ export default function EditUserModal() {
<button
type="submit"
className="bg-purple42-300 text-white rounded-lg p-2 w-full"
disabled={isLoading}
>
Salvar alterações
{isLoading ? (
<svg
className="animate-spin h-5 w-5 mr-3"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
) : (
<span>Atualizar</span>
)}
</button>
</form>
</Dialog.Panel>
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/LeaderBoard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ export function LeaderBoard() {
<LeaderBoardCard
key={user.id}
id={user.id}
name={user.login}
name={user.displayName}
avatar={user.avatar || ""}
score={user.victory}
isFriend={user.login.includes("m")}
//TODO: create functional logic
isFriend={false}
/>
))}
</>
Expand Down

0 comments on commit 1b4960a

Please sign in to comment.