carnet api nc
This commit is contained in:
parent
1acecd3678
commit
d2366a8c74
@ -3,6 +3,9 @@ import { getServerSession } from 'next-auth';
|
|||||||
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
||||||
import { DOMParser } from '@xmldom/xmldom';
|
import { DOMParser } from '@xmldom/xmldom';
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
async function sleep(ms: number) {
|
async function sleep(ms: number) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
@ -10,7 +13,7 @@ async function sleep(ms: number) {
|
|||||||
|
|
||||||
async function parseXMLResponse(response: Response): Promise<any> {
|
async function parseXMLResponse(response: Response): Promise<any> {
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
console.log('XML Response:', text); // Debug log
|
console.log('XML Response:', text);
|
||||||
|
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const xmlDoc = parser.parseFromString(text, 'text/xml');
|
const xmlDoc = parser.parseFromString(text, 'text/xml');
|
||||||
@ -41,9 +44,49 @@ async function parseXMLResponse(response: Response): Promise<any> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getWebDAVCredentials(nextcloudUrl: string, username: string, adminUsername: string, adminPassword: string) {
|
async function createFolder(nextcloudUrl: string, username: string, password: string, folderPath: string) {
|
||||||
|
const response = await fetch(`${nextcloudUrl}/remote.php/dav/files/${encodeURIComponent(username)}/${encodeURIComponent(folderPath)}`, {
|
||||||
|
method: 'MKCOL',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok && response.status !== 405) { // 405 means folder already exists
|
||||||
|
throw new Error(`Failed to create folder ${folderPath}: ${response.status} ${response.statusText}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getWebDAVCredentials(nextcloudUrl: string, username: string, adminUsername: string, adminPassword: string, userId: string) {
|
||||||
try {
|
try {
|
||||||
// First, try to get the user's WebDAV password
|
// Check if credentials exist in database
|
||||||
|
let credentials = await prisma.webDAVCredentials.findUnique({
|
||||||
|
where: { userId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (credentials) {
|
||||||
|
// Verify existing credentials still work
|
||||||
|
const verifyResponse = await fetch(`${nextcloudUrl}/remote.php/dav/files/${encodeURIComponent(username)}/`, {
|
||||||
|
method: 'PROPFIND',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Basic ${Buffer.from(`${username}:${credentials.password}`).toString('base64')}`,
|
||||||
|
'Depth': '1',
|
||||||
|
'Content-Type': 'application/xml',
|
||||||
|
},
|
||||||
|
body: '<?xml version="1.0" encoding="UTF-8"?><d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/></d:prop></d:propfind>',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (verifyResponse.ok) {
|
||||||
|
return credentials.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If verification failed, delete the old credentials
|
||||||
|
await prisma.webDAVCredentials.delete({
|
||||||
|
where: { userId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get user info from Nextcloud
|
||||||
const userInfoResponse = await fetch(`${nextcloudUrl}/ocs/v1.php/cloud/users/${encodeURIComponent(username)}`, {
|
const userInfoResponse = await fetch(`${nextcloudUrl}/ocs/v1.php/cloud/users/${encodeURIComponent(username)}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Basic ${Buffer.from(`${adminUsername}:${adminPassword}`).toString('base64')}`,
|
'Authorization': `Basic ${Buffer.from(`${adminUsername}:${adminPassword}`).toString('base64')}`,
|
||||||
@ -52,18 +95,14 @@ async function getWebDAVCredentials(nextcloudUrl: string, username: string, admi
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!userInfoResponse.ok) {
|
if (!userInfoResponse.ok) {
|
||||||
console.error('Failed to get user info:', await userInfoResponse.text());
|
|
||||||
throw new Error(`Failed to get user info: ${userInfoResponse.status} ${userInfoResponse.statusText}`);
|
throw new Error(`Failed to get user info: ${userInfoResponse.status} ${userInfoResponse.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userInfo = await parseXMLResponse(userInfoResponse);
|
|
||||||
console.log('User Info:', userInfo);
|
|
||||||
|
|
||||||
// Generate a new password
|
// Generate a new password
|
||||||
const newPassword = Math.random().toString(36).slice(-12);
|
const newPassword = Math.random().toString(36).slice(-12);
|
||||||
console.log('Setting new password for user');
|
console.log('Setting new password for user');
|
||||||
|
|
||||||
// Set the user's password directly
|
// Set the user's password
|
||||||
const setPasswordResponse = await fetch(`${nextcloudUrl}/ocs/v1.php/cloud/users/${encodeURIComponent(username)}`, {
|
const setPasswordResponse = await fetch(`${nextcloudUrl}/ocs/v1.php/cloud/users/${encodeURIComponent(username)}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
@ -78,25 +117,22 @@ async function getWebDAVCredentials(nextcloudUrl: string, username: string, admi
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!setPasswordResponse.ok) {
|
if (!setPasswordResponse.ok) {
|
||||||
console.error('Failed to set password:', await setPasswordResponse.text());
|
|
||||||
throw new Error(`Failed to set password: ${setPasswordResponse.status} ${setPasswordResponse.statusText}`);
|
throw new Error(`Failed to set password: ${setPasswordResponse.status} ${setPasswordResponse.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the password was set by trying to authenticate with PROPFIND
|
// Store the new credentials
|
||||||
const verifyResponse = await fetch(`${nextcloudUrl}/remote.php/dav/files/${encodeURIComponent(username)}/`, {
|
credentials = await prisma.webDAVCredentials.create({
|
||||||
method: 'PROPFIND',
|
data: {
|
||||||
headers: {
|
userId,
|
||||||
'Authorization': `Basic ${Buffer.from(`${username}:${newPassword}`).toString('base64')}`,
|
username,
|
||||||
'Depth': '1',
|
password: newPassword,
|
||||||
'Content-Type': 'application/xml',
|
|
||||||
},
|
},
|
||||||
body: '<?xml version="1.0" encoding="UTF-8"?><d:propfind xmlns:d="DAV:"><d:prop><d:resourcetype/></d:prop></d:propfind>',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!verifyResponse.ok) {
|
// Create required folder structure
|
||||||
console.error('Failed to verify password:', await verifyResponse.text());
|
await createFolder(nextcloudUrl, username, newPassword, 'Private');
|
||||||
throw new Error('Password verification failed');
|
await createFolder(nextcloudUrl, username, newPassword, 'Private/Diary');
|
||||||
}
|
await createFolder(nextcloudUrl, username, newPassword, 'Private/Health');
|
||||||
|
|
||||||
return newPassword;
|
return newPassword;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -148,7 +184,8 @@ export async function GET() {
|
|||||||
nextcloudUrl,
|
nextcloudUrl,
|
||||||
nextcloudUsername,
|
nextcloudUsername,
|
||||||
adminUsername,
|
adminUsername,
|
||||||
adminPassword
|
adminPassword,
|
||||||
|
session.user.id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!webdavPassword) {
|
if (!webdavPassword) {
|
||||||
@ -156,7 +193,7 @@ export async function GET() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get user's folders using WebDAV with Basic authentication
|
// Get user's folders using WebDAV with Basic authentication
|
||||||
const webdavUrl = `${nextcloudUrl}/remote.php/dav/files/${encodeURIComponent(nextcloudUsername)}/`;
|
const webdavUrl = `${nextcloudUrl}/remote.php/dav/files/${encodeURIComponent(nextcloudUsername)}/Private/`;
|
||||||
console.log('Requesting WebDAV URL:', webdavUrl);
|
console.log('Requesting WebDAV URL:', webdavUrl);
|
||||||
|
|
||||||
const foldersResponse = await fetch(webdavUrl, {
|
const foldersResponse = await fetch(webdavUrl, {
|
||||||
@ -202,7 +239,7 @@ export async function GET() {
|
|||||||
if (href) {
|
if (href) {
|
||||||
// Extract folder name from href
|
// Extract folder name from href
|
||||||
const folderName = decodeURIComponent(href.split('/').filter(Boolean).pop() || '');
|
const folderName = decodeURIComponent(href.split('/').filter(Boolean).pop() || '');
|
||||||
if (folderName && folderName !== nextcloudUsername) {
|
if (folderName && folderName !== 'Private') {
|
||||||
folders.push(folderName);
|
folders.push(folderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
node_modules/.prisma/client/edge.js
generated
vendored
32
node_modules/.prisma/client/edge.js
generated
vendored
File diff suppressed because one or more lines are too long
24
node_modules/.prisma/client/index-browser.js
generated
vendored
24
node_modules/.prisma/client/index-browser.js
generated
vendored
@ -149,6 +149,26 @@ exports.Prisma.EventScalarFieldEnum = {
|
|||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.MailCredentialsScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
userId: 'userId',
|
||||||
|
email: 'email',
|
||||||
|
password: 'password',
|
||||||
|
host: 'host',
|
||||||
|
port: 'port',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.WebDAVCredentialsScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
userId: 'userId',
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.SortOrder = {
|
exports.Prisma.SortOrder = {
|
||||||
asc: 'asc',
|
asc: 'asc',
|
||||||
desc: 'desc'
|
desc: 'desc'
|
||||||
@ -168,7 +188,9 @@ exports.Prisma.NullsOrder = {
|
|||||||
exports.Prisma.ModelName = {
|
exports.Prisma.ModelName = {
|
||||||
User: 'User',
|
User: 'User',
|
||||||
Calendar: 'Calendar',
|
Calendar: 'Calendar',
|
||||||
Event: 'Event'
|
Event: 'Event',
|
||||||
|
MailCredentials: 'MailCredentials',
|
||||||
|
WebDAVCredentials: 'WebDAVCredentials'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
3230
node_modules/.prisma/client/index.d.ts
generated
vendored
3230
node_modules/.prisma/client/index.d.ts
generated
vendored
File diff suppressed because it is too large
Load Diff
32
node_modules/.prisma/client/index.js
generated
vendored
32
node_modules/.prisma/client/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
node_modules/.prisma/client/package.json
generated
vendored
2
node_modules/.prisma/client/package.json
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "prisma-client-067e3ae165f3d7f955e13b8f5c95a2f095181e1bc0dd7f966e97f0ca575218a3",
|
"name": "prisma-client-c9759cc7a8e2c5f5df4ff9bd3c0aee5a8c3b48f326a42a0aac248c95b4c1be3c",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"browser": "index-browser.js",
|
"browser": "index-browser.js",
|
||||||
|
|||||||
42
node_modules/.prisma/client/schema.prisma
generated
vendored
42
node_modules/.prisma/client/schema.prisma
generated
vendored
@ -12,13 +12,15 @@ datasource db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
email String @unique
|
email String @unique
|
||||||
password String
|
password String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
calendars Calendar[]
|
calendars Calendar[]
|
||||||
events Event[]
|
events Event[]
|
||||||
|
mailCredentials MailCredentials?
|
||||||
|
webdavCredentials WebDAVCredentials?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Calendar {
|
model Calendar {
|
||||||
@ -53,3 +55,29 @@ model Event {
|
|||||||
@@index([calendarId])
|
@@index([calendarId])
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model MailCredentials {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
userId String @unique
|
||||||
|
email String
|
||||||
|
password String
|
||||||
|
host String
|
||||||
|
port Int
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@index([userId])
|
||||||
|
}
|
||||||
|
|
||||||
|
model WebDAVCredentials {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
userId String @unique
|
||||||
|
username String
|
||||||
|
password String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@index([userId])
|
||||||
|
}
|
||||||
|
|||||||
24
node_modules/.prisma/client/wasm.js
generated
vendored
24
node_modules/.prisma/client/wasm.js
generated
vendored
@ -149,6 +149,26 @@ exports.Prisma.EventScalarFieldEnum = {
|
|||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.MailCredentialsScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
userId: 'userId',
|
||||||
|
email: 'email',
|
||||||
|
password: 'password',
|
||||||
|
host: 'host',
|
||||||
|
port: 'port',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.WebDAVCredentialsScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
userId: 'userId',
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.SortOrder = {
|
exports.Prisma.SortOrder = {
|
||||||
asc: 'asc',
|
asc: 'asc',
|
||||||
desc: 'desc'
|
desc: 'desc'
|
||||||
@ -168,7 +188,9 @@ exports.Prisma.NullsOrder = {
|
|||||||
exports.Prisma.ModelName = {
|
exports.Prisma.ModelName = {
|
||||||
User: 'User',
|
User: 'User',
|
||||||
Calendar: 'Calendar',
|
Calendar: 'Calendar',
|
||||||
Event: 'Event'
|
Event: 'Event',
|
||||||
|
MailCredentials: 'MailCredentials',
|
||||||
|
WebDAVCredentials: 'WebDAVCredentials'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,7 +8,7 @@ generator client {
|
|||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
url = env("DATABASE_URL")
|
url = env("NEWSDB_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
@ -20,6 +20,7 @@ model User {
|
|||||||
calendars Calendar[]
|
calendars Calendar[]
|
||||||
events Event[]
|
events Event[]
|
||||||
mailCredentials MailCredentials?
|
mailCredentials MailCredentials?
|
||||||
|
webdavCredentials WebDAVCredentials?
|
||||||
}
|
}
|
||||||
|
|
||||||
model Calendar {
|
model Calendar {
|
||||||
@ -66,5 +67,17 @@ model MailCredentials {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@index([userId])
|
||||||
|
}
|
||||||
|
|
||||||
|
model WebDAVCredentials {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
userId String @unique
|
||||||
|
username String
|
||||||
|
password String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user