Skip to content

Commit

Permalink
Upgrade all dependencies
Browse files Browse the repository at this point in the history
Fix newlines

Remove console.log

Remove signatures

Remove SOB

Remove console.log
  • Loading branch information
Gijsdeman committed Dec 1, 2023
1 parent 8c5124c commit 9f4cd72
Show file tree
Hide file tree
Showing 11 changed files with 676 additions and 4,250 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ db/**/*

# Editors
.idea
*.iml
*.iml

tsconfig.tsbuildinfo
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# We build our container using node:16-alpine
FROM node:16-alpine AS builder
FROM node:20-alpine AS builder
ENV NODE_ENV=development

# Change dir to install dir.
Expand All @@ -22,7 +22,7 @@ RUN npx tsc


# Create production container.
FROM node:16-alpine AS prod
FROM node:20-alpine AS prod

# Set correct dir.
WORKDIR /app
Expand Down
3,877 changes: 218 additions & 3,659 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
"lint:fix": "eslint --fix"
},
"devDependencies": {
"@types/express": "^4.17.17",
"@types/express-session": "^1.17.7",
"@typescript-eslint/eslint-plugin": "^6.4.0",
"@typescript-eslint/parser": "^6.4.0",
"eslint": "^8.47.0",
"@types/express": "^4.17.21",
"@types/express-session": "^1.17.10",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"eslint": "^8.54.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-plugin-import": "^2.28.0",
"eslint-plugin-import": "^2.29.0",
"tslint": "^6.1.3",
"typescript": "^5.1.6"
"typescript": "^5.3.2"
},
"dependencies": {
"@types/node": "^20.5.0",
"@types/node": "^20.10.0",
"axios": "^1.6.2",
"ldapts": "^6.0.0",
"ldapts": "^7.0.7",
"mysql": "^2.18.1",
"replace-in-file": "^7.0.1",
"replace-in-file": "^7.0.2",
"sqlite3": "^5.1.6",
"ts-mailcow-api": "^0.8.4",
"typeorm": "^0.3.17"
Expand Down
137 changes: 1 addition & 136 deletions src/dovecotAPI.ts
Original file line number Diff line number Diff line change
@@ -1,136 +1 @@
import axios, { AxiosInstance } from 'axios';
import {
DovecotData,
DovecotRequestData,
DovecotPermissions,
ActiveDirectoryPermissions,
} from './types';
import { containerConfig } from './index';

let dovecotClient: AxiosInstance;

/**
* Initialize the Dovecot API
*/
export async function initializeDovecotAPI(): Promise<void> {
dovecotClient = axios.create({
baseURL: 'http://172.22.1.250:9000/doveadm/v1',
headers: {
'Content-Type': 'text/plain',
'Authorization': `X-Dovecot-API ${Buffer.from(containerConfig.DOVEADM_API_KEY).toString('base64')}`,
},
});
}

/**
* Get all mailbox subfolders of a mail
* @param mail - email to get all subfolders from
*/
async function getMailboxSubFolders(mail: string): Promise<string[]> {
const mailboxData: DovecotData[] = ((await dovecotClient.post(
'',
[[
'mailboxList',
{
'user': mail,
},
`mailboxList_${mail}`,
]],
)).data)[0][1];

let subFolders: string[] = [];
for (let subFolder of mailboxData) {
if (subFolder.mailbox.startsWith('Shared')) continue;
subFolders.push(subFolder.mailbox);
}

return subFolders;
}

/**
* Set read and write permissions in dovecot
* @param mail - mail for which permissions should be set
* @param users - users that will be getting permissions to the above mail
* @param permission - permissions that will be set
* @param removePermission - whether permissions should be removed or added
*/
export async function setDovecotPermissions(mail: string, users: string[], permission: ActiveDirectoryPermissions, removePermission: boolean) {
let mailboxSubFolders: string[] = [];
let permissionTag;

if (permission == ActiveDirectoryPermissions.mailPermROInbox) {
mailboxSubFolders = mailboxSubFolders.concat(['INBOX', 'Inbox']);
permissionTag = 'PermROInbox';
}

if (permission == ActiveDirectoryPermissions.mailPermROSent) {
if (permissionTag === null) {
permissionTag = 'PermROSent';
} else {
permissionTag = 'PermROInboxSent';
}
mailboxSubFolders.push('Sent');
}

if (permission == ActiveDirectoryPermissions.mailPermRO || ActiveDirectoryPermissions.mailPermRW) {
mailboxSubFolders = await getMailboxSubFolders(mail);
permissionTag = 'PermRO';
}

// Dovecot API requests are very unclear and badly documented
// The idea; you can create an array of requests and send it as one big request
const dovecotRequests : DovecotRequestData[] = [];
for (const subFolder of mailboxSubFolders) {
for (const user of users) {

let rights = [
DovecotPermissions.lookup,
DovecotPermissions.read,
DovecotPermissions.write,
DovecotPermissions.write_seen,
];

if (permission === ActiveDirectoryPermissions.mailPermRW) {
rights = rights.concat([
DovecotPermissions.write_deleted,
DovecotPermissions.insert,
DovecotPermissions.post,
DovecotPermissions.expunge,
DovecotPermissions.create,
DovecotPermissions.delete,
]);
}

const dovecotRequest: DovecotRequestData = [
removePermission ? 'aclRemove' : 'aclSet',
{
'user': mail,
'id': `user=${user}`,
'mailbox': subFolder,
'right': rights,
},
permission === ActiveDirectoryPermissions.mailPermRW ? `PermRW_${mail}_${user}` : `${permissionTag}_${mail}_${user}`,
];

dovecotRequests.push(dovecotRequest);
}
}

// There is a max size of the requests
// Break them up in smaller pieces if necessary
// NOTE from Dovecot docs: It is not guaranteed that requests are processed in order or that the doveadm server does not crash
const dovecotMaxRequestSize: number = 20;
if (dovecotRequests.length > dovecotMaxRequestSize) {
for (let requestsDone: number = 0; requestsDone < dovecotRequests.length; requestsDone += dovecotMaxRequestSize) {
await dovecotClient.post(
'', dovecotRequests.slice(requestsDone, requestsDone + dovecotMaxRequestSize),
);
}
} else {
await dovecotClient.post(
'', dovecotRequests,
);
}
}


import axios, { AxiosInstance } from 'axios';import { DovecotData, DovecotRequestData, DovecotPermissions, ActiveDirectoryPermissions,} from './types';import { containerConfig } from './index';let dovecotClient: AxiosInstance;/** * Initialize the Dovecot API */export async function initializeDovecotAPI(): Promise<void> { dovecotClient = axios.create({ baseURL: 'http://172.22.1.250:9000/doveadm/v1', headers: { 'Content-Type': 'text/plain', 'Authorization': `X-Dovecot-API ${Buffer.from(containerConfig.DOVEADM_API_KEY).toString('base64')}`, }, });}/** * Get all mailbox subfolders of a mail * @param mail - email to get all subfolders from */async function getMailboxSubFolders(mail: string): Promise<string[]> { const mailboxData: DovecotData[] = ((await dovecotClient.post( '', [[ 'mailboxList', { 'user': mail, }, `mailboxList_${mail}`, ]], )).data)[0][1]; let subFolders: string[] = []; for (let subFolder of mailboxData) { if (subFolder.mailbox.startsWith('Shared')) continue; subFolders.push(subFolder.mailbox); } return subFolders;}/** * Set read and write permissions in dovecot * @param mail - mail for which permissions should be set * @param users - users that will be getting permissions to the above mail * @param permission - permissions that will be set * @param removePermission - whether permissions should be removed or added */export async function setDovecotPermissions(mail: string, users: string[], permission: ActiveDirectoryPermissions, removePermission: boolean) { let mailboxSubFolders: string[] = []; let permissionTag; if (permission == ActiveDirectoryPermissions.mailPermROInbox) { mailboxSubFolders = mailboxSubFolders.concat(['INBOX', 'Inbox']); permissionTag = 'PermROInbox'; } if (permission == ActiveDirectoryPermissions.mailPermROSent) { if (permissionTag === null) { permissionTag = 'PermROSent'; } else { permissionTag = 'PermROInboxSent'; } mailboxSubFolders.push('Sent'); } if (permission == ActiveDirectoryPermissions.mailPermRO || ActiveDirectoryPermissions.mailPermRW) { mailboxSubFolders = await getMailboxSubFolders(mail); permissionTag = 'PermRO'; } // Dovecot API requests are very unclear and badly documented // The idea; you can create an array of requests and send it as one big request const dovecotRequests : DovecotRequestData[] = []; for (const subFolder of mailboxSubFolders) { for (const user of users) { let rights = [ DovecotPermissions.lookup, DovecotPermissions.read, DovecotPermissions.write, DovecotPermissions.write_seen, ]; if (permission === ActiveDirectoryPermissions.mailPermRW) { rights = rights.concat([ DovecotPermissions.write_deleted, DovecotPermissions.insert, DovecotPermissions.post, DovecotPermissions.expunge, DovecotPermissions.create, DovecotPermissions.delete, ]); } const dovecotRequest: DovecotRequestData = [ removePermission ? 'aclRemove' : 'aclSet', { 'user': mail, 'id': `user=${user}`, 'mailbox': subFolder, 'right': rights, }, permission === ActiveDirectoryPermissions.mailPermRW ? `PermRW_${mail}_${user}` : `${permissionTag}_${mail}_${user}`, ]; dovecotRequests.push(dovecotRequest); } } // There is a max size of the requests // Break them up in smaller pieces if necessary // NOTE from Dovecot docs: It is not guaranteed that requests are processed in order or that the doveadm server does not crash const dovecotMaxRequestSize: number = 10; if (dovecotRequests.length > dovecotMaxRequestSize) { for (let requestsDone: number = 0; requestsDone < dovecotRequests.length; requestsDone += dovecotMaxRequestSize) { await dovecotClient.post( '', dovecotRequests.slice(requestsDone, requestsDone + dovecotMaxRequestSize), ); } } else { await dovecotClient.post( '', dovecotRequests, ); }}
Expand Down
24 changes: 12 additions & 12 deletions src/entities/SogoUserProfile.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Column, Entity, PrimaryColumn } from 'typeorm';
@Entity()
export class SogoUserProfile {
@PrimaryColumn()
c_uid!: string;

@Column()
c_defaults!: string;

@Column()
c_settings!: string;
}
import { Column, Entity, PrimaryColumn } from 'typeorm';
@Entity()
export class SogoUserProfile {
@PrimaryColumn()
c_uid!: string;

@Column()
c_defaults!: string;

@Column()
c_settings!: string;
}
8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ async function synchronizeUserACL(activeDirectoryUser: ActiveDirectoryUser, perm
attributes: ['memberFlattened'],
})).searchEntries[0] as unknown as ActiveDirectoryUser;

console.log('CHECKING');
console.log(activeDirectoryUser);

await updateLocalUserPermissions(activeDirectoryUser.mail, activeDirectoryPermissionGroup.memberFlattened, permission)
.then(async (changedUsers: ChangedUsers) => {
if (changedUsers.newUsers.length != 0) {
Expand Down Expand Up @@ -346,6 +343,7 @@ async function getUserDataFromActiveDirectory(): Promise<void> {
* Synchronise LDAP users with Mailcow mailboxes and users stores in local DB
*/
async function synchronizeUsersWithActiveDirectory(): Promise<void> {

for (const activeDirectoryUser of activeDirectoryUsers) {
try {
if (!activeDirectoryUser.mail || activeDirectoryUser.mail.length === 0) continue;
Expand All @@ -357,6 +355,8 @@ async function synchronizeUsersWithActiveDirectory(): Promise<void> {
const localUser: LocalUserData = await getLocalUser(mail);
const mailcowUser: MailcowUserData = await getMailcowUser(mail);

// console.log('start checking local user');

if (!localUser.exists) {
console.log(`Adding local user ${mail} (active: ${isActive})`);
await createLocalUser(mail, displayName, isActive);
Expand Down Expand Up @@ -456,7 +456,7 @@ async function synchronizePermissionsWithActiveDirectory(): Promise<void> {
console.log(`Changing SOB of ${activeDirectoryUser.email}`);
const SOBs: string[] = activeDirectoryUser.mailPermSOB.split(';');
await editMailcowUser(activeDirectoryUser.email, { sender_acl: SOBs });
await editUserSignatures(activeDirectoryUser, SOBs);
// await editUserSignatures(activeDirectoryUser, SOBs);
} catch (error) {
console.log(`Ran into an issue when syncing send on behalf of ${activeDirectoryUser.email}. \n\n ${error}`);
}
Expand Down
Loading

0 comments on commit 9f4cd72

Please sign in to comment.