true init commit

This commit is contained in:
2023-08-23 15:40:08 +03:00
parent f8f4ba76ca
commit 2b7ca2afa5
10 changed files with 4238 additions and 174 deletions

109
src/main.ts Normal file
View File

@@ -0,0 +1,109 @@
import { createClient, SearchOptions, Error as LdapError, SearchCallbackResponse } from "ldapjs";
import {
LDAPSearchSettingTab,
DEFAULT_SETTINGS,
LDAPSearchSettings,
} from "./settings";
import { Notice, Plugin } from "obsidian";
import { LDAPModal } from "./modal";
import { renderString } from "nunjucks";
export default class LDAPSearch extends Plugin {
settings: LDAPSearchSettings;
async onload() {
await this.loadSettings();
console.log("LDAP search plugin started");
this.addCommand({
id: "ldap-contact-lookup",
name: "LDAP contact lookup",
callback: () => {
this.ldapsearch();
},
});
this.addSettingTab(new LDAPSearchSettingTab(this.app, this));
}
async ldapsearch() {
const client = createClient({
url: [`ldap://${this.settings.server}:${this.settings.port}`],
});
client.bind(this.settings.login, this.settings.password, (err) => {
if (err) {
new Notice(`LDAP Bind Error: ${err.message}`);
console.error("Bind ERROR", err);
}
});
new LDAPModal(this.app, (username) => {
const fields = this.settings.fields.split(",");
if (this.settings.photoFlag && !fields.contains(this.settings.photoField)){
fields.push(this.settings.photoField);
}
const opts: SearchOptions = {
filter: `(sAMAccountname=${username})`, //TODO: Move to settings
scope: "sub",
attributes: fields,
};
client.search(
this.settings.baseDN,
opts,
(err: LdapError, res: SearchCallbackResponse) => {
res.on("searchEntry", async (entry) => {
console.log("Entry finded");
const myMap: Map<string, string> = new Map<
string,
string
>();
entry.attributes.forEach(async (element) => {
if (element.type !== this.settings.photoField) {
myMap.set(element.type, element.vals[0]);
}
});
if (this.settings.photoFlag) {
entry.attributes.forEach(async (element) => {
if (element.type === this.settings.photoField) {
await app.vault.adapter.writeBinary(`${this.settings.photoPath}/${renderString(this.settings.photoNameTemplate, Object.fromEntries(myMap))}`,
element.buffers[0]
);
}
});
}
console.log(`${this.settings.path}/${renderString(this.settings.fileNameTempalte, Object.fromEntries(myMap))}`);
await app.vault.adapter.write(`${this.settings.path}/${renderString(this.settings.fileNameTempalte, Object.fromEntries(myMap))}`,
renderString(
this.settings.template,
Object.fromEntries(myMap)
))
});
res.on("error", (err) => {
new Notice(`LDAP Error: ${err.message}`);
console.error("error: " + err);
});
}
);
console.log("LDAP finish");
}).open();
}
onunload() {
console.log("LDAP Exit");
}
async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
}
async saveSettings() {
await this.saveData(this.settings);
}
}

35
src/modal.ts Normal file
View File

@@ -0,0 +1,35 @@
import { App, Modal, Setting } from "obsidian";
export class LDAPModal extends Modal {
username: string;
onSubmit: (username: string) => void;
constructor(app: App, onSubmit: (username: string) => void) {
super(app);
this.onSubmit = onSubmit;
}
onOpen(): void {
const { contentEl } = this;
contentEl.createEl("h1", { text: "Enter search term" });
new Setting(contentEl).setName("Search term").addText((text) =>
text.onChange((value) => {
this.username = value;
})
);
new Setting(contentEl)
.addButton((btn) =>
btn
.setButtonText("Submit")
.setCta()
.onClick(() => {
this.close();
this.onSubmit(this.username);
}));
}
onClose(): void {
const { contentEl } = this;
contentEl.empty();
}
}

239
src/settings.ts Normal file
View File

@@ -0,0 +1,239 @@
import { App, PluginSettingTab, Setting } from "obsidian";
import LDAPSearch from "./main";
export interface LDAPSearchSettings {
server: string;
port: string;
login: string;
password: string;
baseDN: string;
fileNameTempalte: string;
template: string;
fields: string;
path: string;
photoPath: string;
photoFlag: boolean;
photoNameTemplate: string;
photoField: string;
}
export const DEFAULT_SETTINGS: LDAPSearchSettings = {
server: "",
port: "389",
login: "",
password: "",
baseDN: "",
fileNameTempalte: "",
template: "",
fields: "",
path: "",
photoFlag: false,
photoPath: "",
photoNameTemplate: "",
photoField: "thumbnailPhoto"
};
export class LDAPSearchSettingTab extends PluginSettingTab {
plugin: LDAPSearch;
constructor(app: App, plugin: LDAPSearch) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "LDAP Search settings." });
new Setting(containerEl).setName("Login").
setDesc("Login or BindDN for LDAP server auth").
addText((text) =>
text
.setValue(this.plugin.settings.login)
.onChange(async (value) => {
this.plugin.settings.login = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("Password").
setDesc("Password for LDAP server auth").
addText((text) =>
text
.setValue(this.plugin.settings.password)
.onChange(async (value) => {
this.plugin.settings.password = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("Host").
setDesc("LDAP server host").
addText((text) =>
text
.setValue(this.plugin.settings.server)
.onChange(async (value) => {
this.plugin.settings.server = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("Port").
setDesc("LDAP server port").
addText((text) =>
text
.setValue(this.plugin.settings.port)
.setPlaceholder("389")
.onChange(async (value) => {
this.plugin.settings.port = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("BaseDN").
setDesc(createFragment((fragment) => {
fragment.append(
"Base object for search. See details ",
fragment.createEl("a", {
text: "here",
href: "https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol#Search_and_compare",
})
);
})).
addText((text) =>
text
.setValue(this.plugin.settings.baseDN)
.onChange(async (value) => {
this.plugin.settings.baseDN = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("Fields").
setDesc("Comma-separated list of fields to be retrieved from LDAP").
addText((text) =>
text
.setValue(this.plugin.settings.fields)
.onChange(async (value) => {
this.plugin.settings.fields = value;
await this.plugin.saveSettings();
})
);
new Setting(containerEl).setName("Target folder").
setDesc("Folder where the contact page will be saved").
addText((text) => {
text
.setValue(this.plugin.settings.path)
.setPlaceholder("/people")
.onChange(async (value) => {
this.plugin.settings.path = value;
await this.plugin.saveSettings();
})
});
new Setting(containerEl).setName("File name template").
setDesc(createFragment((fragment) => {
fragment.append(
"Template for filling with fields received from LDAP. You can use ",
fragment.createEl("a", {
text: "Nunjucks",
href: "https://mozilla.github.io/nunjucks/templating.html",
}),
" library specifications"
);
})).
addText((text)=>{
text
.setValue(this.plugin.settings.fileNameTempalte)
.setPlaceholder("{{ sn }} {{ givenName }}.md")
.onChange(async (value) => {
this.plugin.settings.fileNameTempalte = value;
await this.plugin.saveSettings();
})
})
new Setting(containerEl).setName("Page template").
setDesc(createFragment((fragment) => {
fragment.append(
"Template for filling with fields received from LDAP. You can use ",
fragment.createEl("a", {
text: "Nunjucks",
href: "https://mozilla.github.io/nunjucks/templating.html",
}),
" library specifications"
);
})).
addTextArea((text) => {
text
.setValue(this.plugin.settings.template)
.onChange(async (value) => {
this.plugin.settings.template = value;
await this.plugin.saveSettings();
})
text.inputEl.setAttr("rows", 25);
text.inputEl.setAttr("cols", 50);
}
);
containerEl.createEl("h5", {
text: "Advanced Settings",
});
new Setting(containerEl)
.setName("Store photo")
.setDesc("Enable or disable saving photo from ldap")
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.photoFlag)
.onChange(async (value) => {
this.plugin.settings.photoFlag = value;
await this.plugin.saveSettings();
})
})
new Setting(containerEl)
.setName("Photo LDAP fields")
.setDesc("LDAP fields contains photo")
.addText((text)=>{
text.setValue(this.plugin.settings.photoField)
.onChange(async (value) => {
this.plugin.settings.photoField = value;
await this.plugin.saveSettings();
})
})
new Setting(containerEl)
.setName("Target folder")
.setDesc("Folder where the contact photo will be saved")
.addText((text) => {
text.setValue(this.plugin.settings.photoPath)
.onChange(async (value) => {
this.plugin.settings.photoPath = value;
await this.plugin.saveSettings();
})
});
new Setting(containerEl)
.setName("Photo file name template")
.setDesc(createFragment((fragment)=>{
fragment.append(
"Template for photo file name. You can use the same fields as in the page template. The ",
fragment.createEl("a", {
text: "Nunjucks",
href: "https://mozilla.github.io/nunjucks/templating.html",
}),
" library is used"
)
}))
.addText((text)=>{
text.setValue(this.plugin.settings.photoNameTemplate)
.onChange(async (value) => {
this.plugin.settings.photoNameTemplate = value;
await this.plugin.saveSettings();
})
})
}
}