Skip to content

Commit

Permalink
Merge pull request #1887 from Giveth/feat/user_sitemap_list
Browse files Browse the repository at this point in the history
Feat/user sitemap list
  • Loading branch information
kkatusic authored Dec 26, 2024
2 parents 82dfc17 + fd8ea0e commit b41c543
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/entities/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,18 @@ export class User extends BaseEntity {
return `givethId-${this.id}`;
}
}

@ObjectType()
export class UserPublicData extends BaseEntity {
@Field(_type => String, { nullable: true })
firstName?: string;

@Field(_type => String, { nullable: true })
lastName?: string;

@Field(_type => String, { nullable: true })
name?: string;

@Field(_type => String, { nullable: true })
walletAddress?: string;
}
81 changes: 81 additions & 0 deletions src/resolvers/userResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
SEED_DATA,
} from '../../test/testUtils';
import {
allUsersBasicDataQuery,
refreshUserScores,
updateUser,
userByAddress,
Expand All @@ -34,6 +35,7 @@ describe('updateUser() test cases', updateUserTestCases);
describe('userByAddress() test cases', userByAddressTestCases);
describe('refreshUserScores() test cases', refreshUserScoresTestCases);
describe('userEmailVerification() test cases', userEmailVerification);
describe('allUsersBasicData() test cases', allUsersBasicData);
// TODO I think we can delete addUserVerification query
// describe('addUserVerification() test cases', addUserVerificationTestCases);
function refreshUserScoresTestCases() {
Expand Down Expand Up @@ -1169,3 +1171,82 @@ function userEmailVerification() {
});
});
}

function allUsersBasicData() {
describe('allUsersBasicData Test Cases', () => {
it('should return the default number of users when no limit or skip is provided', async () => {
// Create sample users
await saveUserDirectlyToDb(generateRandomEtheriumAddress());
await saveUserDirectlyToDb(generateRandomEtheriumAddress());

// Execute the query
const result = await axios.post(graphqlUrl, {
query: allUsersBasicDataQuery,
});

// Assertions
const { users, totalCount } = result.data.data.allUsersBasicData;
assert.isArray(users, 'Users should be an array');
assert.isTrue(users.length > 0, 'Should return at least one user');
assert.isNumber(totalCount, 'Total count should be a number');
});

it('should return a limited number of users when a limit is specified', async () => {
// Create sample users
await saveUserDirectlyToDb(generateRandomEtheriumAddress());
await saveUserDirectlyToDb(generateRandomEtheriumAddress());

// Execute the query with a limit
const result = await axios.post(graphqlUrl, {
query: allUsersBasicDataQuery,
variables: { limit: 1 },
});

// Assertions
const { users } = result.data.data.allUsersBasicData;
assert.isArray(users, 'Users should be an array');
assert.equal(users.length, 1, 'Should return only one user');
});

it('should skip the specified number of users', async () => {
await saveUserDirectlyToDb(generateRandomEtheriumAddress());
await saveUserDirectlyToDb(generateRandomEtheriumAddress());

// Execute the query with skip
const result = await axios.post(graphqlUrl, {
query: allUsersBasicDataQuery,
variables: { skip: 1, limit: 1 },
});

// Assertions
const { users } = result.data.data.allUsersBasicData;
assert.isArray(users, 'Users should be an array');
assert.equal(users.length, 1, 'Should return only one user');
});

it('should not include sensitive fields like email in the response', async () => {
// Execute the query
const result = await axios.post(graphqlUrl, {
query: allUsersBasicDataQuery,
variables: { skip: 0, limit: 10 },
});

// Assertions
const { users } = result.data.data.allUsersBasicData;
assert.isArray(users, 'Users should be an array');
assert.isTrue(users.length > 0, 'Should return at least one user');

// If any users exist, ensure email and password is not part of the response
if (users.length > 0) {
assert.isUndefined(
users[0].email,
'Email should not be included in the response',
);
assert.isUndefined(
users[0].password,
'Password should not be included in the response',
);
}
});
});
}
37 changes: 36 additions & 1 deletion src/resolvers/userResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import {
Arg,
Ctx,
Field,
Int,
Mutation,
ObjectType,
Query,
Resolver,
} from 'type-graphql';
import { Repository } from 'typeorm';

import { User } from '../entities/user';
import { User, UserPublicData } from '../entities/user';
import { AccountVerificationInput } from './types/accountVerificationInput';
import { ApolloContext } from '../types/ApolloContext';
import { i18n, translationErrorMessagesKeys } from '../utils/errorMessages';
Expand Down Expand Up @@ -43,6 +44,15 @@ class UserRelatedAddressResponse {
hasDonated: boolean;
}

@ObjectType()
class AllUsersPublicData {
@Field(_type => [UserPublicData])
users: UserPublicData[];

@Field(_type => Number)
totalCount: number;
}

@Resolver(_of => User)
export class UserResolver {
constructor(private readonly userRepository: Repository<User>) {
Expand Down Expand Up @@ -422,4 +432,29 @@ export class UserResolver {

return 'VERIFICATION_SUCCESS';
}

@Query(_returns => AllUsersPublicData)
async allUsersBasicData(
@Arg('limit', _type => Int, { nullable: true }) limit: number = 50,
@Arg('skip', _type => Int, { nullable: true }) skip: number = 0,
): Promise<AllUsersPublicData> {
const query = this.userRepository
.createQueryBuilder('user')
.select([
'user.firstName',
'user.lastName',
'user.name',
'user.walletAddress',
])
.skip(skip)
.take(limit);

// Execute the query and fetch results
const [users, totalCount] = await query.getManyAndCount();

return {
users,
totalCount,
};
}
}
15 changes: 15 additions & 0 deletions test/graphqlQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2609,3 +2609,18 @@ export const fetchRecurringDonationsByDateQuery = `
}
}
`;

// GraphQL query for fetching all users' basic data
export const allUsersBasicDataQuery = `
query ($limit: Int, $skip: Int) {
allUsersBasicData(limit: $limit, skip: $skip) {
users {
firstName
lastName
name
walletAddress
}
totalCount
}
}
`;

0 comments on commit b41c543

Please sign in to comment.