Skip to content
2 changes: 1 addition & 1 deletion .github/Dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
interval: "weekly"
2 changes: 1 addition & 1 deletion apps/backend/src/api/routes/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import * as Sentry from '@sentry/nestjs';
@ApiTags('Auth')
@Controller('/auth')
export class AuthController {
constructor(
constructor(
private _authService: AuthService,
private _emailService: EmailService
) {}
Expand Down
20 changes: 19 additions & 1 deletion apps/backend/src/api/routes/settings.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/o
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 { User } from 'facebook-nodejs-business-sdk';

This comment was marked as outdated.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, I pushed change

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')
Expand Down Expand Up @@ -46,4 +52,16 @@ 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 || !AuthChecker.comparePassword(body.oldPassword, userWithPassword.password)) {

This comment was marked as outdated.

Copy link
Author

Choose a reason for hiding this comment

The 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

return false;
}
return this._userService.updatePassword(user.id, body.password);
}
}
10 changes: 10 additions & 0 deletions apps/frontend/src/components/layout/settings.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { Autopost } from '@gitroom/frontend/components/autopost/autopost';
import { useT } from '@gitroom/react/translation/get.transation.service.client';
import { SVGLine } from '@gitroom/frontend/components/launches/launches.component';
import { GlobalSettings } from '@gitroom/frontend/components/settings/global.settings';
import { ChangePassword } from '../settings/change-password.component';
export const SettingsPopup: FC<{
getRef?: Ref<any>;
}> = (props) => {
Expand Down Expand Up @@ -105,6 +106,9 @@ export const SettingsPopup: FC<{
if (user?.tier?.public_api && isGeneral && showLogout) {
arr.push({ tab: 'api', label: t('public_api', 'Public API') });
}
if(showLogout) {
arr.push({ tab: 'change_password', label: t('change_password', 'Change Password') });
}

return arr;
}, [user, isGeneral, showLogout, t]);
Expand Down Expand Up @@ -193,6 +197,12 @@ export const SettingsPopup: FC<{
</div>
)}

{tab === 'change_password' && showLogout && (
<div>
<ChangePassword />
</div>
)}

{tab === 'api' &&
!!user?.tier?.public_api &&
isGeneral &&
Expand Down
106 changes: 106 additions & 0 deletions apps/frontend/src/components/settings/change-password.component.tsx
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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "لقد أرسلنا لك بريدًا إلكترونيًا يحتوي على رابط لإعادة تعيين كلمة المرور الخاصة بك.",
"change_password": "تغيير كلمة المرور",
"we_successfully_reset_your_password_you_can_now_login_with_your": "تمت إعادة تعيين كلمة المرور بنجاح. يمكنك الآن تسجيل الدخول باستخدام",
"we_successfully_changed_your_password": "لقد قمنا بتغيير كلمة المرور الخاصة بك بنجاح.",
"password_change_failed": "فشل تغيير كلمة المرور الخاصة بك. يرجى المحاولة مرة أخرى.",
"click_here_to_go_back_to_login": "انقر هنا للعودة إلى تسجيل الدخول",
"activate_your_account": "فعّل حسابك",
"thank_you_for_registering": "شكرًا لتسجيلك!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "ابحث عن قناة",
"label_select_channel": "اختر قناة",
"label_new_password": "كلمة المرور الجديدة",
"label_old_password": "كلمة المرور القديمة",
"label_repeat_password": "أعد إدخال كلمة المرور",
"label_platform": "المنصة",
"label_price_per_post": "السعر لكل منشور",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "আমরা আপনার পাসওয়ার্ড রিসেট করার জন্য একটি লিংক সহ একটি ইমেইল পাঠিয়েছি।",
"change_password": "পাসওয়ার্ড পরিবর্তন করুন",
"we_successfully_reset_your_password_you_can_now_login_with_your": "আমরা সফলভাবে আপনার পাসওয়ার্ড রিসেট করেছি। আপনি এখন আপনার সাথে লগইন করতে পারেন",
"we_successfully_changed_your_password": "আমরা সফলভাবে আপনার পাসওয়ার্ড পরিবর্তন করেছি।",
"password_change_failed": "পাসওয়ার্ড পরিবর্তন ব্যর্থ হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।",
"click_here_to_go_back_to_login": "লগইনে ফিরে যেতে এখানে ক্লিক করুন",
"activate_your_account": "আপনার অ্যাকাউন্ট সক্রিয় করুন",
"thank_you_for_registering": "নিবন্ধনের জন্য ধন্যবাদ!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "চ্যানেল অনুসন্ধান",
"label_select_channel": "চ্যানেল নির্বাচন করুন",
"label_new_password": "নতুন পাসওয়ার্ড",
"label_old_password": "পুরানো পাসওয়ার্ড",
"label_repeat_password": "পাসওয়ার্ড পুনরায় দিন",
"label_platform": "প্ল্যাটফর্ম",
"label_price_per_post": "প্রতি পোস্টের মূল্য",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "Wir haben Ihnen eine E-Mail mit einem Link zum Zurücksetzen Ihres Passworts gesendet.",
"change_password": "Passwort ändern",
"we_successfully_reset_your_password_you_can_now_login_with_your": "Wir haben Ihr Passwort erfolgreich zurückgesetzt. Sie können sich jetzt anmelden mit ihrem",
"we_successfully_changed_your_password": "Wir haben Ihr Passwort erfolgreich geändert.",
"password_change_failed": "Passwortänderung fehlgeschlagen. Bitte versuchen Sie es erneut.",
"click_here_to_go_back_to_login": "Klicken Sie hier, um zum Login zurückzukehren",
"activate_your_account": "Aktivieren Sie Ihr Konto",
"thank_you_for_registering": "Vielen Dank für Ihre Registrierung!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "Kanal durchsuchen",
"label_select_channel": "Kanal auswählen",
"label_new_password": "Neues Passwort",
"label_old_password": "Altes Passwort",
"label_repeat_password": "Passwort wiederholen",
"label_platform": "Plattform",
"label_price_per_post": "Preis pro Beitrag",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "We have send you an email with a link to reset your password.",
"change_password": "Change Password",
"we_successfully_reset_your_password_you_can_now_login_with_your": "We successfully reset your password. You can now login with your",
"we_successfully_changed_your_password": "Your password change has failed. Please try again.",
"password_change_failed": "We successfully changed your password",
"click_here_to_go_back_to_login": "Click here to go back to login",
"activate_your_account": "Activate your account",
"thank_you_for_registering": "Thank you for registering!",
Expand Down Expand Up @@ -419,6 +421,7 @@
"label_search_channel": "Search Channel",
"label_select_channel": "Select Channel",
"label_new_password": "New Password",
"label_old_password": "Old Password",
"label_repeat_password": "Repeat Password",
"label_platform": "Platform",
"label_price_per_post": "Price per post",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "Te hemos enviado un correo electrónico con un enlace para restablecer tu contraseña.",
"change_password": "Cambiar contraseña",
"we_successfully_reset_your_password_you_can_now_login_with_your": "Hemos restablecido tu contraseña correctamente. Ahora puedes iniciar sesión con tu",
"we_successfully_changed_your_password": "Hemos cambiado tu contraseña con éxito.",
"password_change_failed": "Error al cambiar la contraseña. Por favor, inténtalo de nuevo.",
"click_here_to_go_back_to_login": "Haz clic aquí para volver a iniciar sesión",
"activate_your_account": "Activa tu cuenta",
"thank_you_for_registering": "¡Gracias por registrarte!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "Buscar canal",
"label_select_channel": "Seleccionar canal",
"label_new_password": "Nueva contraseña",
"label_old_password": "Contraseña antigua",
"label_repeat_password": "Repetir contraseña",
"label_platform": "Plataforma",
"label_price_per_post": "Precio por publicación",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "Nous vous avons envoyé un e-mail avec un lien pour réinitialiser votre mot de passe.",
"change_password": "Changer le mot de passe",
"we_successfully_reset_your_password_you_can_now_login_with_your": "Nous avons réinitialisé votre mot de passe avec succès. Vous pouvez maintenant vous connecter avec votre",
"we_successfully_changed_your_password": "Nous avons changé votre mot de passe avec succès.",
"password_change_failed": "Échec du changement de mot de passe. Veuillez réessayer.",
"click_here_to_go_back_to_login": "Cliquez ici pour revenir à la connexion",
"activate_your_account": "Activez votre compte",
"thank_you_for_registering": "Merci pour votre inscription !",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "Rechercher un canal",
"label_select_channel": "Sélectionner un canal",
"label_new_password": "Nouveau mot de passe",
"label_old_password": "Ancien mot de passe",
"label_repeat_password": "Répéter le mot de passe",
"label_platform": "Plateforme",
"label_price_per_post": "Prix par publication",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "שלחנו לך אימייל עם קישור לאיפוס הסיסמה שלך.",
"change_password": "שנה סיסמה",
"we_successfully_reset_your_password_you_can_now_login_with_your": "איפסנו את הסיסמה שלך בהצלחה. כעת תוכל להתחבר עם",
"we_successfully_changed_your_password": "שינינו את הסיסמה שלך בהצלחה.",
"password_change_failed": "שינוי הסיסמה נכשל. אנא נסה שוב.",
"click_here_to_go_back_to_login": "לחץ כאן כדי לחזור להתחברות",
"activate_your_account": "הפעל את החשבון שלך",
"thank_you_for_registering": "תודה שנרשמת!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "חפש ערוץ",
"label_select_channel": "בחר ערוץ",
"label_new_password": "סיסמה חדשה",
"label_old_password": "סיסמה ישנה",
"label_repeat_password": "חזור על הסיסמה",
"label_platform": "פלטפורמה",
"label_price_per_post": "מחיר לפוסט",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "Ti abbiamo inviato un'email con un link per reimpostare la password.",
"change_password": "Cambia password",
"we_successfully_reset_your_password_you_can_now_login_with_your": "Abbiamo reimpostato con successo la tua password. Ora puoi accedere con la tua",
"we_successfully_changed_your_password": "Abbiamo cambiato con successo la tua password.",
"password_change_failed": "Cambio della password non riuscito. Per favore riprova.",
"click_here_to_go_back_to_login": "Clicca qui per tornare al login",
"activate_your_account": "Attiva il tuo account",
"thank_you_for_registering": "Grazie per esserti registrato!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "Cerca canale",
"label_select_channel": "Seleziona canale",
"label_new_password": "Nuova password",
"label_old_password": "Vecchia password",
"label_repeat_password": "Ripeti password",
"label_platform": "Piattaforma",
"label_price_per_post": "Prezzo per post",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@
"we_have_send_you_an_email_with_a_link_to_reset_your_password": "パスワードをリセットするためのリンクを記載したメールを送信しました。",
"change_password": "パスワードを変更",
"we_successfully_reset_your_password_you_can_now_login_with_your": "パスワードのリセットが完了しました。新しいパスワードでログインできます。",
"we_successfully_changed_your_password": "パスワードの変更が完了しました。",
"password_change_failed": "パスワードの変更に失敗しました。もう一度お試しください。",
"click_here_to_go_back_to_login": "ログイン画面に戻るにはこちらをクリックしてください",
"activate_your_account": "アカウントを有効化",
"thank_you_for_registering": "ご登録ありがとうございます!",
Expand Down Expand Up @@ -418,6 +420,7 @@
"label_search_channel": "チャンネルを検索",
"label_select_channel": "チャンネルを選択",
"label_new_password": "新しいパスワード",
"label_old_password": "古いパスワード",
"label_repeat_password": "パスワードを再入力",
"label_platform": "プラットフォーム",
"label_price_per_post": "投稿ごとの価格",
Expand Down
Loading