Skip to content

Commit

Permalink
Clan test might not work
Browse files Browse the repository at this point in the history
  • Loading branch information
YoctoProductions committed Feb 14, 2025
1 parent 94b0849 commit 8983a36
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 6 deletions.
18 changes: 18 additions & 0 deletions api/src/accounts/accounts.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FindOneOptions, Repository } from 'typeorm';
import { Account } from './account.entity';
import * as config from '../config';
import validateUsername from 'src/helpers/validateUsername';
import validateClan from 'src/helpers/validateClan';
import { Transaction } from 'src/transactions/transactions.entity';
import * as cosmetics from '../cosmetics.json';
import CacheObj from 'src/Cache';
Expand Down Expand Up @@ -275,6 +276,23 @@ export class AccountsService {
}
}

async changeClan(id: number, clan: string) {
// validate clan
if(validateClan(clan)) {
return {error: validateClan(clan)};
}
const account = await this.getById(id);

account.clan = clan;
account.lastClanChange = new Date();
try {
await this.accountsRepository.save(account);
return {success: true};
} catch(e) {
return {error: 'Failed to update clan, '+ e.message};
}
}

async update(id: number, updates: Partial<Account>) {
const account = await this.accountsRepository.findOneBy({ id });
if (!account) {
Expand Down
5 changes: 5 additions & 0 deletions api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ export class AuthController {
let result = await this.authService.changeUsername(request.account, request.body.newUsername);
return result;
}
@Post('change-clan')
async changeClan(@Req() request) {
let result = await this.authService.changeClan(request.account, request.body.newClan);
return result;
}

setCookie(res: Response, key: string, value: string) {
return res.cookie(key, value, {
Expand Down
16 changes: 14 additions & 2 deletions api/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class AuthService {
try {
account = await this.accountsService.findOne({ where: { secret: data.secret } });
} catch (e) {
throw new UnauthorizedException('User does not exists');
throw new UnauthorizedException('User does not exist');
}

return { account: this.accountsService.sanitizeAccount(account), secret: data.secret };
Expand All @@ -53,7 +53,7 @@ export class AuthService {
}

if (!account) {
throw new UnauthorizedException('User does not exists');
throw new UnauthorizedException('User does not exist');
}
if (!(await account.checkPassword(data.password))) {
throw new UnauthorizedException('Wrong password');
Expand Down Expand Up @@ -97,6 +97,18 @@ export class AuthService {
return {error: e.message};
}
}
async changeClan(account: Account, newClan: string) {
try {
let result = await this.accountsService.changeClan(account.id, newClan);
if(result.success) {
(result as any).secret = account.secret;
}
return result;
} catch (e) {
console.log(e);
return {error: e.message};
}
}

async updateAccount(account: Account) {
return this.accountsService.update(account.id, account);
Expand Down
4 changes: 3 additions & 1 deletion api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface ConfigProps {

usernameWaitTime: number;
usernameLength: [number, number];
clanLength: [number, number];
}

export const config: ConfigProps = {
Expand All @@ -21,5 +22,6 @@ export const config: ConfigProps = {
serverSecret: process.env.SERVER_SECRET || 'server-secret',

usernameWaitTime: 7 * 24 * 60 * 60 * 1000, // 7 days
usernameLength: [1, 16]
usernameLength: [1, 16],
clanLength: [1, 4],
};
22 changes: 22 additions & 0 deletions api/src/helpers/validateClan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { config } from "src/config";
import * as filter from 'leo-profanity';

export default function validateClan(clan: string): string {
// just to be safe
if(clan === "__proto__" || clan === "constructor" || clan === "prototype") {
return "Clan is not allowed";
}
// normal validation
if(clan.length < config.clanLength[0] || clan.length > config.clanLength[1]) {
return `Clan must be between ${config.clanLength[0]} and ${config.clanLength[1]} characters`;
}
var regex = /^[a-zA-Z0-9]+$/g;
if(!clan.match(regex)) {
return "Clan can only contain letters and numbers";
}
var containsProfanity = filter.check(clan);
if(containsProfanity) {
return "Clan contains a bad word!\nIf this is a mistake, please contact an admin.";
}
return "";
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 31 additions & 1 deletion client/src/redux/account/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import api from '../../api';
export type AccountState = {
email: string;
username: string;
clan: string;
isLoggedIn: boolean;
secret: string;
gems: number;
Expand All @@ -16,6 +17,7 @@ export type AccountState = {
const initialState: AccountState = {
email: '',
username: '',
clan: '',
secret: '',
isLoggedIn: false,
gems: 0,
Expand Down Expand Up @@ -85,7 +87,30 @@ export const changeNameAsync = createAsyncThunk(
}
}
);
export const changeClanAsync = createAsyncThunk(
'account/changeClan',
async (newClan: string, { getState, dispatch }) => {
// const state: any = getState();
try {
const response = await api.postAsync(`${api.endpoint}/auth/change-clan?now=${Date.now()}`, {
newClan
});

if (response.error) {
alert(response.error);
} else if (response.success) {
alert('Clan changed successfully');
// Dispatching actions to update name and token in the state
dispatch(setClan(newClan));
dispatch(setSecret(response.secret));
}
} catch (error) {
// Handle any other errors, such as network issues
console.error(error);
alert('An error occurred while changing the clan.');
}
}
);

const accountSlice = createSlice({
name: 'account',
Expand All @@ -94,6 +119,7 @@ const accountSlice = createSlice({
clearAccount: (state) => {
state.email = '';
state.username = '';
state.clan = '';
state.secret = '';
state.gems = 0;
state.ultimacy = 0;
Expand All @@ -106,6 +132,7 @@ const accountSlice = createSlice({
setAccount: (state, action) => {
state.email = action.payload.email;
state.username = action.payload.username;
state.clan = action.payload.clan;
state.isLoggedIn = true;
const previousToken = state.secret;
state.secret = action.payload.secret;
Expand All @@ -128,6 +155,9 @@ const accountSlice = createSlice({
setName: (state, action) => {
state.username = action.payload;
},
setClan: (state, action) => {
state.clan = action.payload;
},
setSecret: (state, action) => {
state.secret = action.payload;
console.log('Token updated');
Expand All @@ -148,5 +178,5 @@ const accountSlice = createSlice({
},
});

export const { setAccount, clearAccount, setName, setSecret } = accountSlice.actions;
export const { setAccount, clearAccount, setName, setSecret, setClan } = accountSlice.actions;
export default accountSlice.reducer;
13 changes: 11 additions & 2 deletions client/src/ui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import LoginModal from './modals/LoginModal';
import SignupModal from './modals/SignupModal';
import ConnectionError from './modals/ConnectionError';

import { clearAccount, setAccount, logoutAsync, changeNameAsync } from '../redux/account/slice';
import { clearAccount, setAccount, logoutAsync, changeNameAsync, changeClanAsync } from '../redux/account/slice';
import { selectAccount } from '../redux/account/selector';
import api from '../api';

Expand Down Expand Up @@ -235,8 +235,12 @@ function App() {
const onChangeName = () => {
const newName = prompt('What do you want to change your name to? Please note that you can only change your name once every 7 days.');
if (!newName) return;

dispatch(changeNameAsync(newName) as any);
}
const onChangeClan = () => {
const newClan = prompt('What do you want to change your clan to? Clans can only contain letters, numbers, and up to 4 characters.');
if (!newClan) return;
dispatch(changeClanAsync(newClan) as any);
}
const openShop = () => {
setModal(<ShopModal account={account} />);
Expand Down Expand Up @@ -380,6 +384,11 @@ function App() {
<FontAwesomeIcon icon={faICursor} /> Change Name
</a>
</li>
<li>
<a className="dropdown-item" href="#" onClick={onChangeClan}>
<FontAwesomeIcon icon={faICursor} /> Change Clan
</a>
</li>
<li><a className="dropdown-item" href="#" onClick={onLogout}>
<FontAwesomeIcon icon={faSignOut} /> Logout
</a></li>
Expand Down
7 changes: 7 additions & 0 deletions client/src/ui/game/Leaderboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@
font-size: 22px;
white-space: nowrap;
}

.leaderboard-clan {
color: red;
text-align: right;
position: fixed;
transform: translate(-100%);
}
1 change: 1 addition & 0 deletions client/src/ui/game/Leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function LeaderboardLine({ player }: any) {
}
return (
<div className="leaderboard-line">
{player.account?.clan && <span className="leaderboard-clan">[{player.account.clan.toUpperCase()}] &nbsp;</span>}
<span className="leaderboard-place">#{player.place}: </span>
<span className="leaderboard-name" style={player.account ? { color: specialColors[player.name.toLowerCase() as any] ? specialColors[player.name.toLowerCase() as any] : '#3333ff' } : {}}>{player.name}
{player.account?.rank && <span style={{color: getRankColor(player.account.rank)}}> (#{player.account.rank})</span>}
Expand Down

0 comments on commit 8983a36

Please sign in to comment.