-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Feature/1164 #1165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feature/1164 #1165
Changes from 10 commits
fc094a2
5400629
909d714
0148f54
0eea872
4f4465e
c9eb3b2
f71199c
f30d047
e9ca64b
9ffe670
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ import * as Sentry from '@sentry/nestjs'; | |
| @ApiTags('Auth') | ||
| @Controller('/auth') | ||
| export class AuthController { | ||
| constructor( | ||
| constructor( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't modify any files unrelated to this PR. |
||
| private _authService: AuthService, | ||
| private _emailService: EmailService | ||
| ) {} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,22 @@ | ||
| import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common'; | ||
| import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request'; | ||
| import { Organization } from '@prisma/client'; | ||
| import { Organization, User } from '@prisma/client'; | ||
| import { CheckPolicies } from '@gitroom/backend/services/auth/permissions/permissions.ability'; | ||
| import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service'; | ||
| import { AddTeamMemberDto } from '@gitroom/nestjs-libraries/dtos/settings/add.team.member.dto'; | ||
| import { ApiTags } from '@nestjs/swagger'; | ||
| import { AuthorizationActions, Sections } from '@gitroom/backend/services/auth/permissions/permission.exception.class'; | ||
| import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request'; | ||
| import { UsersService } from '@gitroom/nestjs-libraries/database/prisma/users/users.service'; | ||
| import { ChangePasswordDto } from '@gitroom/nestjs-libraries/dtos/settings/change.password.dto'; | ||
| import { AuthService as AuthChecker } from '@gitroom/helpers/auth/auth.service'; | ||
|
|
||
| @ApiTags('Settings') | ||
| @Controller('/settings') | ||
| export class SettingsController { | ||
| constructor( | ||
| private _organizationService: OrganizationService | ||
| private _organizationService: OrganizationService, | ||
| private _userService: UsersService | ||
| ) {} | ||
|
|
||
| @Get('/team') | ||
|
|
@@ -46,4 +51,19 @@ export class SettingsController { | |
| ) { | ||
| return this._organizationService.deleteTeamMember(org, id); | ||
| } | ||
|
|
||
| @Post('/change-password') | ||
| async changePassword( | ||
| @GetUserFromRequest() user: User, | ||
| @Body() body: ChangePasswordDto | ||
| ) { | ||
| const userWithPassword = await this._userService.getUserById(user.id); | ||
| if(userWithPassword.providerName !== 'LOCAL') { | ||
| return false; | ||
| } | ||
| if(!userWithPassword || !AuthChecker.comparePassword(body.oldPassword, userWithPassword.password)) { | ||
This comment was marked as outdated.
Sorry, something went wrong.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, changed it and also in setting tab on frontend part I added condition that only LOCAL users can see change password tab
This comment was marked as outdated.
Sorry, something went wrong.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| return false; | ||
| } | ||
| return this._userService.updatePassword(user.id, body.password); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| 'use client'; | ||
|
|
||
| import { useForm, SubmitHandler, FormProvider } from 'react-hook-form'; | ||
| import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; | ||
| import { Button } from '@gitroom/react/form/button'; | ||
| import { Input } from '@gitroom/react/form/input'; | ||
| import { useMemo, useState } from 'react'; | ||
| import { classValidatorResolver } from '@hookform/resolvers/class-validator'; | ||
| import { ChangePasswordDto } from '@gitroom/nestjs-libraries/dtos/settings/change.password.dto'; | ||
| import { useT } from '@gitroom/react/translation/get.transation.service.client'; | ||
| import { useToaster } from '@gitroom/react/toaster/toaster'; | ||
| type Inputs = { | ||
| oldPassword: string; | ||
| password: string; | ||
| repeatPassword: string; | ||
| }; | ||
|
|
||
| export const ChangePassword = () => { | ||
| const [loading, setLoading] = useState(false); | ||
| const t = useT(); | ||
| const toaster = useToaster(); | ||
| const [state, setState] = useState(false); | ||
| const resolver = useMemo(() => { | ||
| return classValidatorResolver(ChangePasswordDto); | ||
| }, []); | ||
| const form = useForm<Inputs>({ | ||
| resolver, | ||
| mode: 'onChange', | ||
| }); | ||
| const fetchData = useFetch(); | ||
| const onSubmit: SubmitHandler<Inputs> = async (data) => { | ||
| setLoading(true); | ||
|
|
||
| const response = await fetchData('/settings/change-password', { | ||
| method: 'POST', | ||
| body: JSON.stringify({ | ||
| ...data, | ||
| }), | ||
| }); | ||
| const change = await response.json(); | ||
| console.log(change); | ||
| if (!change) { | ||
| form.setError('password', { | ||
| type: 'manual', | ||
| message: t('password_change_failed', 'Your password change has failed. Please try again.'), | ||
| }); | ||
| toaster.show('Password change failed', 'warning'); | ||
| setLoading(false); | ||
| return false; | ||
| } | ||
| setState(true); | ||
| setLoading(false); | ||
| }; | ||
| return ( | ||
| <div className="flex flex-col"> | ||
| <h3 className="text-[20px]">{t('change_password', 'Change Password')}</h3> | ||
| <FormProvider {...form}> | ||
| <form> | ||
| {!state ? ( | ||
| <> | ||
| <div className="space-y-4 text-textColor"> | ||
| <Input | ||
| label="Old Password" | ||
| translationKey="label_old_password" | ||
| {...form.register('oldPassword')} | ||
| type="password" | ||
| placeholder={t('label_old_password', 'Password')} | ||
| /> | ||
| <Input | ||
| label="New Password" | ||
| translationKey="label_new_password" | ||
| {...form.register('password')} | ||
| type="password" | ||
| placeholder={t('label_password', 'Password')} | ||
| /> | ||
| <Input | ||
| label="Repeat Password" | ||
| translationKey="label_repeat_password" | ||
| {...form.register('repeatPassword')} | ||
| type="password" | ||
| placeholder={t('label_repeat_password', 'Repeat Password')} | ||
| /> | ||
| </div> | ||
| <div className="text-center mt-6"> | ||
| <div className="w-full flex"> | ||
| <Button className="flex-1" loading={loading} onClick={form.handleSubmit(onSubmit)}> | ||
| {t('change_password', 'Change Password')} | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| </> | ||
| ) : ( | ||
| <> | ||
| <div className="text-start mt-6"> | ||
| {t( | ||
| 'we_successfully_changed_your_password', | ||
| 'We successfully changed your password' | ||
| )} | ||
| </div> | ||
| </> | ||
| )} | ||
| </form> | ||
| </FormProvider> | ||
| </div> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { makeId } from "@gitroom/nestjs-libraries/services/make.is"; | ||
| import { IsDefined, IsIn, IsString, MinLength, ValidateIf } from "class-validator"; | ||
|
|
||
| export class ChangePasswordDto { | ||
| @IsString() | ||
| @IsDefined() | ||
| oldPassword: string; | ||
|
|
||
| @IsString() | ||
| @IsDefined() | ||
| @MinLength(3) | ||
| password: string; | ||
|
|
||
| @IsString() | ||
| @IsDefined() | ||
| @IsIn([makeId(10)], { | ||
| message: 'Passwords do not match', | ||
| }) | ||
| @ValidateIf((o) => o.password !== o.repeatPassword) | ||
| repeatPassword: string; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't modify any files unrelated to this PR.