update
This commit is contained in:
@@ -120,6 +120,29 @@ class AtemschutzController {
|
||||
}
|
||||
}
|
||||
|
||||
async getByUserId(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { userId } = req.params as Record<string, string>;
|
||||
if (!isValidUUID(userId)) {
|
||||
res.status(400).json({ success: false, message: 'Ungültige Benutzer-ID' });
|
||||
return;
|
||||
}
|
||||
const callerId = getUserId(req);
|
||||
const callerGroups: string[] = (req.user as any)?.groups ?? [];
|
||||
const privileged = ['dashboard_admin', 'dashboard_kommando', 'dashboard_atemschutz', 'dashboard_moderator'];
|
||||
const isPrivileged = callerGroups.some((g) => privileged.includes(g));
|
||||
if (userId !== callerId && !isPrivileged) {
|
||||
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
|
||||
return;
|
||||
}
|
||||
const record = await atemschutzService.getByUserId(userId);
|
||||
res.status(200).json({ success: true, data: record ?? null });
|
||||
} catch (error) {
|
||||
logger.error('Atemschutz getByUserId error', { error, userId: req.params.userId });
|
||||
res.status(500).json({ success: false, message: 'Atemschutzstatus konnte nicht geladen werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async getMyStatus(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const userId = getUserId(req);
|
||||
|
||||
@@ -16,7 +16,9 @@ import {
|
||||
type AppRole = 'admin' | 'kommandant' | 'mitglied';
|
||||
|
||||
function getRole(req: Request): AppRole {
|
||||
return (req.user as any)?.role ?? 'mitglied';
|
||||
// req.userRole is set by requirePermission() for non-owner paths.
|
||||
// Fall back to req.user.role (JWT claim) and finally to 'mitglied'.
|
||||
return (req as any).userRole ?? (req.user as any)?.role ?? 'mitglied';
|
||||
}
|
||||
|
||||
function canWrite(req: Request): boolean {
|
||||
@@ -209,14 +211,16 @@ class MemberController {
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await memberService.updateMemberProfile(
|
||||
await memberService.updateMemberProfile(
|
||||
userId,
|
||||
parseResult.data as any,
|
||||
updaterId
|
||||
);
|
||||
|
||||
// Return full MemberWithProfile so the frontend state stays consistent
|
||||
const fullMember = await memberService.getMemberById(userId);
|
||||
logger.info('updateMember', { userId, updatedBy: updaterId });
|
||||
res.status(200).json({ success: true, data: profile });
|
||||
res.status(200).json({ success: true, data: fullMember });
|
||||
} catch (error: any) {
|
||||
if (error?.message === 'Mitgliedsprofil nicht gefunden.') {
|
||||
res.status(404).json({ success: false, message: error.message });
|
||||
|
||||
@@ -145,7 +145,7 @@ class NextcloudController {
|
||||
return;
|
||||
}
|
||||
const token = req.params.token as string;
|
||||
const { message } = req.body;
|
||||
const { message, replyTo } = req.body;
|
||||
if (!token || !message || typeof message !== 'string' || message.trim().length === 0) {
|
||||
res.status(400).json({ success: false, message: 'Token und Nachricht erforderlich' });
|
||||
return;
|
||||
@@ -154,7 +154,8 @@ class NextcloudController {
|
||||
res.status(400).json({ success: false, message: 'Nachricht zu lang' });
|
||||
return;
|
||||
}
|
||||
await nextcloudService.sendMessage(token, message.trim(), credentials.loginName, credentials.appPassword);
|
||||
const replyToNum = (typeof replyTo === 'number' && replyTo > 0) ? replyTo : undefined;
|
||||
await nextcloudService.sendMessage(token, message.trim(), credentials.loginName, credentials.appPassword, replyToNum);
|
||||
res.status(200).json({ success: true, data: null });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') {
|
||||
@@ -302,6 +303,118 @@ class NextcloudController {
|
||||
res.status(500).json({ success: false, message: 'Raum konnte nicht als gelesen markiert werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async searchUsers(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) {
|
||||
res.status(200).json({ success: true, data: [] });
|
||||
return;
|
||||
}
|
||||
const query = (req.query.search as string) ?? '';
|
||||
const results = await nextcloudService.searchUsers(query, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data: results });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') {
|
||||
await userService.clearNextcloudCredentials(req.user!.id);
|
||||
res.status(200).json({ success: true, data: [] });
|
||||
return;
|
||||
}
|
||||
logger.error('searchUsers error', { error });
|
||||
res.status(500).json({ success: false, message: 'Benutzersuche fehlgeschlagen' });
|
||||
}
|
||||
}
|
||||
|
||||
async createRoom(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) {
|
||||
res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' });
|
||||
return;
|
||||
}
|
||||
const { roomType, invite, roomName } = req.body;
|
||||
if (typeof roomType !== 'number' || !invite || typeof invite !== 'string') {
|
||||
res.status(400).json({ success: false, message: 'roomType und invite erforderlich' });
|
||||
return;
|
||||
}
|
||||
const result = await nextcloudService.createRoom(roomType, invite, roomName, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data: result });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') {
|
||||
await userService.clearNextcloudCredentials(req.user!.id);
|
||||
res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' });
|
||||
return;
|
||||
}
|
||||
logger.error('createRoom error', { error });
|
||||
res.status(500).json({ success: false, message: 'Raum konnte nicht erstellt werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async addReaction(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) { res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
const token = req.params.token;
|
||||
const messageId = parseInt(req.params.messageId, 10);
|
||||
const { reaction } = req.body;
|
||||
if (!token || isNaN(messageId) || !reaction) { res.status(400).json({ success: false, message: 'Parameter fehlen' }); return; }
|
||||
await nextcloudService.addReaction(token, messageId, reaction, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data: null });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') { await userService.clearNextcloudCredentials(req.user!.id); res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
logger.error('addReaction error', { error });
|
||||
res.status(500).json({ success: false, message: 'Reaktion konnte nicht hinzugefügt werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async removeReaction(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) { res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
const token = req.params.token;
|
||||
const messageId = parseInt(req.params.messageId, 10);
|
||||
const reaction = req.query.reaction as string;
|
||||
if (!token || isNaN(messageId) || !reaction) { res.status(400).json({ success: false, message: 'Parameter fehlen' }); return; }
|
||||
await nextcloudService.removeReaction(token, messageId, reaction, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data: null });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') { await userService.clearNextcloudCredentials(req.user!.id); res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
logger.error('removeReaction error', { error });
|
||||
res.status(500).json({ success: false, message: 'Reaktion konnte nicht entfernt werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async getReactions(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) { res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
const token = req.params.token;
|
||||
const messageId = parseInt(req.params.messageId, 10);
|
||||
if (!token || isNaN(messageId)) { res.status(400).json({ success: false, message: 'Parameter fehlen' }); return; }
|
||||
const data = await nextcloudService.getReactions(token, messageId, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') { await userService.clearNextcloudCredentials(req.user!.id); res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
logger.error('getReactions error', { error });
|
||||
res.status(500).json({ success: false, message: 'Reaktionen konnten nicht geladen werden' });
|
||||
}
|
||||
}
|
||||
|
||||
async getPoll(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const credentials = await userService.getNextcloudCredentials(req.user!.id);
|
||||
if (!credentials) { res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
const token = req.params.token;
|
||||
const pollId = parseInt(req.params.pollId, 10);
|
||||
if (!token || isNaN(pollId)) { res.status(400).json({ success: false, message: 'Parameter fehlen' }); return; }
|
||||
const data = await nextcloudService.getPollDetails(token, pollId, credentials.loginName, credentials.appPassword);
|
||||
res.status(200).json({ success: true, data });
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NEXTCLOUD_AUTH_INVALID') { await userService.clearNextcloudCredentials(req.user!.id); res.status(401).json({ success: false, message: 'Nextcloud nicht verbunden' }); return; }
|
||||
logger.error('getPoll error', { error });
|
||||
res.status(500).json({ success: false, message: 'Abstimmung konnte nicht geladen werden' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new NextcloudController();
|
||||
|
||||
@@ -9,8 +9,9 @@ const router = Router();
|
||||
|
||||
router.get('/', authenticate, atemschutzController.list.bind(atemschutzController));
|
||||
router.get('/stats', authenticate, atemschutzController.getStats.bind(atemschutzController));
|
||||
router.get('/my-status', authenticate, atemschutzController.getMyStatus.bind(atemschutzController));
|
||||
router.get('/:id', authenticate, atemschutzController.getOne.bind(atemschutzController));
|
||||
router.get('/my-status', authenticate, atemschutzController.getMyStatus.bind(atemschutzController));
|
||||
router.get('/user/:userId', authenticate, atemschutzController.getByUserId.bind(atemschutzController));
|
||||
router.get('/:id', authenticate, atemschutzController.getOne.bind(atemschutzController));
|
||||
|
||||
// ── Write — gruppenfuehrer+ ─────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -139,6 +139,8 @@ interface NextcloudChatMessage {
|
||||
messageType: string;
|
||||
systemMessage: string;
|
||||
messageParameters: Record<string, any>;
|
||||
reactions: Record<string, any>;
|
||||
reactionsSelf: string[];
|
||||
}
|
||||
|
||||
async function getAllConversations(loginName: string, appPassword: string): Promise<NextcloudConversation[]> {
|
||||
@@ -255,6 +257,8 @@ async function getMessages(token: string, loginName: string, appPassword: string
|
||||
messageType: m.messageType ?? '',
|
||||
systemMessage: m.systemMessage ?? '',
|
||||
messageParameters: m.messageParameters ?? {},
|
||||
reactions: m.reactions ?? {},
|
||||
reactionsSelf: m.reactionsSelf ?? [],
|
||||
}));
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
@@ -274,7 +278,7 @@ async function getMessages(token: string, loginName: string, appPassword: string
|
||||
}
|
||||
}
|
||||
|
||||
async function sendMessage(token: string, message: string, loginName: string, appPassword: string): Promise<void> {
|
||||
async function sendMessage(token: string, message: string, loginName: string, appPassword: string, replyTo?: number): Promise<void> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
@@ -283,7 +287,7 @@ async function sendMessage(token: string, message: string, loginName: string, ap
|
||||
try {
|
||||
await httpClient.post(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v1/chat/${encodeURIComponent(token)}`,
|
||||
{ message },
|
||||
{ message, ...(replyTo !== undefined ? { replyTo } : {}) },
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
@@ -560,5 +564,224 @@ async function getFilePreview(
|
||||
}
|
||||
}
|
||||
|
||||
async function searchUsers(query: string, loginName: string, appPassword: string): Promise<any[]> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await httpClient.get(
|
||||
`${baseUrl}/ocs/v2.php/core/autocomplete/get?search=${encodeURIComponent(query)}&limit=20&itemType=&itemId=&shareTypes[]=0&shareTypes[]=1&shareTypes[]=7&format=json`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
return (response.data?.ocs?.data ?? []).map((u: any) => ({ id: u.id, label: u.label, source: u.source }));
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.searchUsers failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.searchUsers failed', { error });
|
||||
throw new Error('Failed to search users');
|
||||
}
|
||||
}
|
||||
|
||||
async function createRoom(roomType: number, invite: string, roomName: string | undefined, loginName: string, appPassword: string): Promise<{ token: string }> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await httpClient.post(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v4/room`,
|
||||
{ roomType, invite, ...(roomName ? { roomName } : {}) },
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
return { token: response.data?.ocs?.data?.token as string };
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.createRoom failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.createRoom failed', { error });
|
||||
throw new Error('Failed to create room');
|
||||
}
|
||||
}
|
||||
|
||||
async function addReaction(token: string, messageId: number, reaction: string, loginName: string, appPassword: string): Promise<void> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
await httpClient.post(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v1/reaction/${encodeURIComponent(token)}/${messageId}`,
|
||||
{ reaction },
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.addReaction failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.addReaction failed', { error });
|
||||
throw new Error('Failed to add reaction');
|
||||
}
|
||||
}
|
||||
|
||||
async function removeReaction(token: string, messageId: number, reaction: string, loginName: string, appPassword: string): Promise<void> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
await httpClient.delete(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v1/reaction/${encodeURIComponent(token)}/${messageId}`,
|
||||
{
|
||||
params: { reaction },
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.removeReaction failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.removeReaction failed', { error });
|
||||
throw new Error('Failed to remove reaction');
|
||||
}
|
||||
}
|
||||
|
||||
async function getReactions(token: string, messageId: number, loginName: string, appPassword: string): Promise<Record<string, any>> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await httpClient.get(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v1/reaction/${encodeURIComponent(token)}/${messageId}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
return response.data?.ocs?.data ?? {};
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.getReactions failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.getReactions failed', { error });
|
||||
throw new Error('Failed to get reactions');
|
||||
}
|
||||
}
|
||||
|
||||
async function getPollDetails(token: string, pollId: number, loginName: string, appPassword: string): Promise<Record<string, any>> {
|
||||
const baseUrl = environment.nextcloudUrl;
|
||||
if (!baseUrl || !isValidServiceUrl(baseUrl)) {
|
||||
throw new Error('NEXTCLOUD_URL is not configured or is not a valid service URL');
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await httpClient.get(
|
||||
`${baseUrl}/ocs/v2.php/apps/spreed/api/v1/poll/${encodeURIComponent(token)}/${pollId}`,
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Basic ${Buffer.from(loginName + ':' + appPassword).toString('base64')}`,
|
||||
'OCS-APIRequest': 'true',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
return response.data?.ocs?.data ?? {};
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
const err = new Error('Nextcloud authentication invalid');
|
||||
(err as any).code = 'NEXTCLOUD_AUTH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (axios.isAxiosError(error)) {
|
||||
logger.error('NextcloudService.getPollDetails failed', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
});
|
||||
throw new Error(`Nextcloud API error: ${error.response?.status ?? 'unknown'}`);
|
||||
}
|
||||
logger.error('NextcloudService.getPollDetails failed', { error });
|
||||
throw new Error('Failed to get poll details');
|
||||
}
|
||||
}
|
||||
|
||||
export type { NextcloudChatMessage, GetMessagesOptions };
|
||||
export default { initiateLoginFlow, pollLoginFlow, getConversations, getAllConversations, getMessages, sendMessage, markAsRead, uploadFileToTalk, downloadFile, getFilePreview };
|
||||
export default { initiateLoginFlow, pollLoginFlow, getConversations, getAllConversations, getMessages, sendMessage, markAsRead, uploadFileToTalk, downloadFile, getFilePreview, searchUsers, createRoom, addReaction, removeReaction, getReactions, getPollDetails };
|
||||
|
||||
Reference in New Issue
Block a user