refactor: usersControl
This commit is contained in:
@@ -31,13 +31,13 @@ app.use('/', indexRoute);
|
|||||||
|
|
||||||
// "users"
|
// "users"
|
||||||
const usersIndexRoute = require('./routes/users/index')(sequelize);
|
const usersIndexRoute = require('./routes/users/index')(sequelize);
|
||||||
const usersShowRoute = require('./routes/users/show')(sequelize);
|
|
||||||
const usersFindRoute = require('./routes/users/find')(sequelize);
|
const usersFindRoute = require('./routes/users/find')(sequelize);
|
||||||
|
const usersSearchRoute = require('./routes/users/search')(sequelize);
|
||||||
const signUpRoute = require('./routes/users/signup')(sequelize);
|
const signUpRoute = require('./routes/users/signup')(sequelize);
|
||||||
const signInRoute = require('./routes/users/signin')(sequelize);
|
const signInRoute = require('./routes/users/signin')(sequelize);
|
||||||
app.use('/users', usersIndexRoute);
|
app.use('/users', usersIndexRoute);
|
||||||
app.use('/users', usersShowRoute);
|
|
||||||
app.use('/users', usersFindRoute);
|
app.use('/users', usersFindRoute);
|
||||||
|
app.use('/users', usersSearchRoute);
|
||||||
app.use('/users', signUpRoute);
|
app.use('/users', signUpRoute);
|
||||||
app.use('/users', signInRoute);
|
app.use('/users', signInRoute);
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,31 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const defineUser = require('../../models/users');
|
const defineUser = require('../../models/users');
|
||||||
const defineMember = require('../../models/members');
|
const { DataTypes } = require('sequelize');
|
||||||
const { DataTypes, Op } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
module.exports = function (sequelize) {
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
const User = defineUser(sequelize, DataTypes);
|
const User = defineUser(sequelize, DataTypes);
|
||||||
const Member = defineMember(sequelize, DataTypes);
|
|
||||||
|
|
||||||
router.get('/find', verifySignedIn, async (req, res) => {
|
router.get('/find/:userId', verifySignedIn, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { projectId, search } = req.query;
|
const userId = req.params.userId;
|
||||||
if (!projectId || !search) {
|
if (!userId) {
|
||||||
return res.status(400).json({ error: 'projectId and search text are required' });
|
return res.status(400).json({ error: 'userId is required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
let where = {
|
try {
|
||||||
[Op.or]: [{ email: { [Op.like]: `%${search}%` } }, { username: { [Op.like]: `%${search}%` } }],
|
const user = await User.findByPk(userId, {
|
||||||
};
|
attributes: ['id', 'username', 'role', 'avatarPath'],
|
||||||
|
|
||||||
let excludeIdArray = [];
|
|
||||||
const members = await Member.findAll({
|
|
||||||
where: { projectId },
|
|
||||||
attributes: ['userId'],
|
|
||||||
});
|
});
|
||||||
excludeIdArray = members.map((member) => member.userId);
|
if (!user) {
|
||||||
excludeIdArray.push(req.userId);
|
return res.status(404).send('User not found');
|
||||||
where.id = { [Op.notIn]: excludeIdArray };
|
}
|
||||||
|
res.json(user);
|
||||||
const users = await User.findAll({
|
} catch (error) {
|
||||||
where,
|
console.error(error);
|
||||||
limit: 7,
|
res.status(500).send('Internal Server Error');
|
||||||
});
|
}
|
||||||
res.json(users);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
res.status(500).send('Internal Server Error');
|
res.status(500).send('Internal Server Error');
|
||||||
|
|||||||
44
backend/routes/users/search.js
Normal file
44
backend/routes/users/search.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const defineUser = require('../../models/users');
|
||||||
|
const defineMember = require('../../models/members');
|
||||||
|
const { DataTypes, Op } = require('sequelize');
|
||||||
|
|
||||||
|
module.exports = function (sequelize) {
|
||||||
|
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
||||||
|
const User = defineUser(sequelize, DataTypes);
|
||||||
|
const Member = defineMember(sequelize, DataTypes);
|
||||||
|
|
||||||
|
router.get('/search', verifySignedIn, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { projectId, search } = req.query;
|
||||||
|
if (!projectId || !search) {
|
||||||
|
return res.status(400).json({ error: 'projectId and search text are required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
let where = {
|
||||||
|
[Op.or]: [{ email: { [Op.like]: `%${search}%` } }, { username: { [Op.like]: `%${search}%` } }],
|
||||||
|
};
|
||||||
|
|
||||||
|
let excludeIdArray = [];
|
||||||
|
const members = await Member.findAll({
|
||||||
|
where: { projectId },
|
||||||
|
attributes: ['userId'],
|
||||||
|
});
|
||||||
|
excludeIdArray = members.map((member) => member.userId);
|
||||||
|
excludeIdArray.push(req.userId);
|
||||||
|
where.id = { [Op.notIn]: excludeIdArray };
|
||||||
|
|
||||||
|
const users = await User.findAll({
|
||||||
|
where,
|
||||||
|
limit: 7,
|
||||||
|
});
|
||||||
|
res.json(users);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).send('Internal Server Error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return router;
|
||||||
|
};
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const defineUser = require('../../models/users');
|
|
||||||
const { DataTypes } = require('sequelize');
|
|
||||||
|
|
||||||
module.exports = function (sequelize) {
|
|
||||||
const { verifySignedIn } = require('../../middleware/auth')(sequelize);
|
|
||||||
const User = defineUser(sequelize, DataTypes);
|
|
||||||
|
|
||||||
router.get('/:userId', verifySignedIn, async (req, res) => {
|
|
||||||
try {
|
|
||||||
const userId = req.params.userId;
|
|
||||||
if (!userId) {
|
|
||||||
return res.status(400).json({ error: 'userId is required' });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const user = await User.findByPk(userId, {
|
|
||||||
attributes: ['id', 'username', 'role', 'avatarPath'],
|
|
||||||
});
|
|
||||||
if (!user) {
|
|
||||||
return res.status(404).send('User not found');
|
|
||||||
}
|
|
||||||
res.json(user);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).send('Internal Server Error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).send('Internal Server Error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return router;
|
|
||||||
};
|
|
||||||
@@ -5,7 +5,7 @@ import { Button, Input, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter
|
|||||||
import { SettingsMessages } from '@/types/settings';
|
import { SettingsMessages } from '@/types/settings';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
import { UserType } from '@/types/user';
|
import { UserType } from '@/types/user';
|
||||||
import { searchUsers } from './membersControl';
|
import { searchUsers } from '@/utils/usersControl';
|
||||||
import CandidatesTable from './CandidatesTable';
|
import CandidatesTable from './CandidatesTable';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -32,7 +32,7 @@ export default function AddMemberDialog({ isOpen, projectId, onCancel, onAddMemb
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await searchUsers(context.token.access_token, projectId, searchText);
|
const data = await searchUsers(context.token.access_token, Number(projectId), searchText);
|
||||||
setCandidates(data);
|
setCandidates(data);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error in effect:', error.message);
|
console.error('Error in effect:', error.message);
|
||||||
|
|||||||
@@ -24,29 +24,6 @@ async function fetchProjectMembers(jwt: string, projectId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchUsers(jwt: string, projectId: string, searchText: string) {
|
|
||||||
const fetchOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${jwt}`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const url = `${apiServer}/users/find?projectId=${projectId}&search=${searchText}`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, fetchOptions);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('Error fetching data:', error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addMember(jwt: string, userId: string, projectId: string) {
|
async function addMember(jwt: string, userId: string, projectId: string) {
|
||||||
const fetchOptions = {
|
const fetchOptions = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -114,4 +91,4 @@ async function updateMember(jwt: string, userId: string, projectId: string, role
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { fetchProjectMembers, searchUsers, addMember, deleteMember, updateMember };
|
export { fetchProjectMembers, addMember, deleteMember, updateMember };
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ import { ProjectType } from '@/types/project';
|
|||||||
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog';
|
||||||
import { useRouter } from '@/src/navigation';
|
import { useRouter } from '@/src/navigation';
|
||||||
import ProjectDialog from '@/components/ProjectDialog';
|
import ProjectDialog from '@/components/ProjectDialog';
|
||||||
import Config from '@/config/config';
|
|
||||||
import { UserType } from '@/types/user';
|
import { UserType } from '@/types/user';
|
||||||
const apiServer = Config.apiServer;
|
import { findUser } from '@/utils/usersControl';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@@ -44,29 +43,6 @@ export default function SettingsPage({ projectId, messages, locale }: Props) {
|
|||||||
username: '',
|
username: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetchUser(jwt: string, userId: string) {
|
|
||||||
const fetchOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
Authorization: `Bearer ${jwt}`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const url = `${apiServer}/users/${userId}`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, fetchOptions);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('Error fetching data:', error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchDataEffect() {
|
async function fetchDataEffect() {
|
||||||
if (!context.isSignedIn()) {
|
if (!context.isSignedIn()) {
|
||||||
@@ -78,7 +54,7 @@ export default function SettingsPage({ projectId, messages, locale }: Props) {
|
|||||||
setProject(data);
|
setProject(data);
|
||||||
|
|
||||||
if (data.userId) {
|
if (data.userId) {
|
||||||
const ownerData = await fetchUser(context.token.access_token, data.userId);
|
const ownerData = await findUser(context.token.access_token, data.userId);
|
||||||
setOwner(ownerData);
|
setOwner(ownerData);
|
||||||
} else {
|
} else {
|
||||||
console.error('failed to get project owner id');
|
console.error('failed to get project owner id');
|
||||||
|
|||||||
50
frontend/utils/usersControl.ts
Normal file
50
frontend/utils/usersControl.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import Config from '@/config/config';
|
||||||
|
const apiServer = Config.apiServer;
|
||||||
|
|
||||||
|
async function findUser(jwt: string, userId: number) {
|
||||||
|
const fetchOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${jwt}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = `${apiServer}/users/find/${userId}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, fetchOptions);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error fetching data:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchUsers(jwt: string, projectId: number, searchText: string) {
|
||||||
|
const fetchOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${jwt}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = `${apiServer}/users/search?projectId=${projectId}&search=${searchText}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, fetchOptions);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Error fetching data:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { findUser, searchUsers };
|
||||||
Reference in New Issue
Block a user