test runnung
This commit is contained in:
parent
af96a136a1
commit
90d4d77e4b
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
ldap-data*
|
||||
|
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
4
README.md
Normal file
4
README.md
Normal file
@ -0,0 +1,4 @@
|
||||
## LDAP Admin Application
|
||||
|
||||
Webapplikation zur Pflege von LDAP-Accounts und Gruppen,
|
||||
eingebetteter Apache Directory Server
|
12
etc/jetty.xml
Normal file
12
etc/jetty.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.security.HashLoginService">
|
||||
<Set name="name">Administration Area</Set>
|
||||
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
1
etc/realm.properties
Normal file
1
etc/realm.properties
Normal file
@ -0,0 +1 @@
|
||||
peter: Test123,login,admins
|
53
ldif/ldap-example-data.ldif
Normal file
53
ldif/ldap-example-data.ldif
Normal file
@ -0,0 +1,53 @@
|
||||
version: 1
|
||||
|
||||
dn: dc=saastest,dc=example,dc=com
|
||||
objectclass: top
|
||||
objectclass: domain
|
||||
administrativeRole: accessControlSpecificArea
|
||||
dc: saastest
|
||||
|
||||
dn: cn=saastestAuthenticationRequirementsACISubentry,dc=saastest,dc=example,dc=com
|
||||
objectClass: accessControlSubentry
|
||||
objectClass: subentry
|
||||
objectClass: top
|
||||
subtreeSpecification: { }
|
||||
prescriptiveACI: { identificationTag "subtreeFullAccessACI", precedence 11, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { name { "uid=application,ou=bind,dc=saastest,dc=example,dc=com" } }, userPermissions { { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantCompare, grantBrowse, grantRename, grantRemove, grantAdd, grantRead, grantFilterMatch, grantReturnDN, grantModify } } } } }
|
||||
prescriptiveACI: { identificationTag "allUsersACI", precedence 9, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems { attributeType { userPassword } }, grantsAndDenials { denyRead, denyFilterMatch, denyCompare } }, { protectedItems { entry, allUserAttributeTypesAndValues }, grantsAndDenials { grantCompare, grantBrowse,grantDiscloseOnError, grantRead, grantFilterMatch, grantReturnDN } } } } }
|
||||
cn: saastestAuthenticationRequirementsACISubentry
|
||||
|
||||
dn: ou=groups,dc=saastest,dc=example,dc=com
|
||||
objectClass: top
|
||||
objectClass: organizationalUnit
|
||||
ou: groups
|
||||
|
||||
dn: ou=users,dc=saastest,dc=example,dc=com
|
||||
objectClass: top
|
||||
objectClass: organizationalUnit
|
||||
ou: users
|
||||
|
||||
dn: ou=bind,dc=saastest,dc=example,dc=com
|
||||
objectClass: top
|
||||
objectClass: organizationalUnit
|
||||
ou: bind
|
||||
|
||||
dn: uid=admin,ou=users,dc=saastest,dc=example,dc=com
|
||||
objectClass: top
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: person
|
||||
objectClass: organizationalPerson
|
||||
cn: system administrator
|
||||
sn: administrator
|
||||
displayName: Directory Superuser
|
||||
uid: admin
|
||||
userPassword: admin-secret
|
||||
|
||||
dn: uid=application,ou=bind,dc=saastest,dc=example,dc=com
|
||||
objectClass: top
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: person
|
||||
objectClass: organizationalPerson
|
||||
cn: application bind user
|
||||
sn: administrator
|
||||
displayName: Application User
|
||||
uid: application
|
||||
userPassword: app-secret
|
7
ldif/master-passwd.ldif
Normal file
7
ldif/master-passwd.ldif
Normal file
@ -0,0 +1,7 @@
|
||||
version:1
|
||||
|
||||
dn: uid=admin,ou=system
|
||||
changetype: modify
|
||||
replace: userPassword
|
||||
userPassword: streng-geheim
|
||||
-
|
121
pom.xml
Normal file
121
pom.xml
Normal file
@ -0,0 +1,121 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.jalin.ldapadmin</groupId>
|
||||
<artifactId>ldapadmin</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>LDAP Admin Webapp</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<env>dev</env>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>dev</id>
|
||||
<properties>
|
||||
<env>dev</env>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>test</id>
|
||||
<properties>
|
||||
<env>test</env>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
<properties>
|
||||
<env>prod</env>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||
<version>2.3.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-service</artifactId>
|
||||
<version>2.0.0.AM25</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.2.3</version>
|
||||
<configuration>
|
||||
<archiveClasses>true</archiveClasses>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.4.19.v20190610</version>
|
||||
<configuration>
|
||||
<jettyXml>etc/jetty.xml</jettyXml>
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
<webApp>
|
||||
<contextPath>/</contextPath>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArgument></compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>ldapadmin</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
1
src/main/filters/filter-dev.properties
Normal file
1
src/main/filters/filter-dev.properties
Normal file
@ -0,0 +1 @@
|
||||
filtered.stage=dev
|
1
src/main/filters/filter-prod.properties
Normal file
1
src/main/filters/filter-prod.properties
Normal file
@ -0,0 +1 @@
|
||||
filtered.stage=prod
|
1
src/main/filters/filter-test.properties
Normal file
1
src/main/filters/filter-test.properties
Normal file
@ -0,0 +1 @@
|
||||
filtered.stage=test
|
45
src/main/java/de/jalin/ldapadmin/beans/Group.java
Normal file
45
src/main/java/de/jalin/ldapadmin/beans/Group.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.jalin.ldapadmin.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Group implements Serializable, LDAPBean {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String dn;
|
||||
private String name;
|
||||
private List<String> members;
|
||||
|
||||
public Group() {
|
||||
members = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public void setMembers(List<String> members) {
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDn() {
|
||||
return dn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDn(String dn) {
|
||||
this.dn = dn;
|
||||
}
|
||||
|
||||
}
|
9
src/main/java/de/jalin/ldapadmin/beans/LDAPBean.java
Normal file
9
src/main/java/de/jalin/ldapadmin/beans/LDAPBean.java
Normal file
@ -0,0 +1,9 @@
|
||||
package de.jalin.ldapadmin.beans;
|
||||
|
||||
public interface LDAPBean {
|
||||
|
||||
public String getDn();
|
||||
|
||||
public void setDn(String dn);
|
||||
|
||||
}
|
27
src/main/java/de/jalin/ldapadmin/beans/MembershipCheck.java
Normal file
27
src/main/java/de/jalin/ldapadmin/beans/MembershipCheck.java
Normal file
@ -0,0 +1,27 @@
|
||||
package de.jalin.ldapadmin.beans;
|
||||
|
||||
public class MembershipCheck {
|
||||
|
||||
private User user;
|
||||
private Group group;
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(Group group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getChecked() {
|
||||
return user != null && group != null && user.getGroups().contains(group.getDn()) ? "checked" : ""; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
126
src/main/java/de/jalin/ldapadmin/beans/User.java
Normal file
126
src/main/java/de/jalin/ldapadmin/beans/User.java
Normal file
@ -0,0 +1,126 @@
|
||||
package de.jalin.ldapadmin.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.jalin.ldapadmin.ldap.PasswordValidator;
|
||||
import de.jalin.ldapadmin.ldap.SimplePasswordException;
|
||||
|
||||
public class User implements Serializable, LDAPBean {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String dn;
|
||||
private String login;
|
||||
private String password;
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
private String displayname;
|
||||
private String email;
|
||||
private String phone;
|
||||
private String mobile;
|
||||
private List<String> groups;
|
||||
|
||||
public User() {
|
||||
groups = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public User(final String login) {
|
||||
this.login = login;
|
||||
groups = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setAndValidatePassword(String password) throws SimplePasswordException {
|
||||
final PasswordValidator validator = new PasswordValidator();
|
||||
validator.validate(password);
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public void setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getDisplayname() {
|
||||
return displayname;
|
||||
}
|
||||
|
||||
public void setDisplayname(String displayname) {
|
||||
this.displayname = displayname;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getMobile() {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public void setMobile(String mobile) {
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
public List<String> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public void setGroups(List<String> groups) {
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getFirstname() + " " + getLastname() + " (" + getLogin() + ", " + getEmail() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDn() {
|
||||
return dn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDn(String dn) {
|
||||
this.dn = dn;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package de.jalin.ldapadmin.beans;
|
||||
|
||||
public class ValidationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String fieldname;
|
||||
private final String condition;
|
||||
|
||||
public ValidationException(final String fieldname, final String condition) {
|
||||
this.fieldname = fieldname;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
public String getFieldname() {
|
||||
return fieldname;
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
public class AlreadyBoundException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String name;
|
||||
|
||||
public AlreadyBoundException(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
125
src/main/java/de/jalin/ldapadmin/ldap/GroupsDAO.java
Normal file
125
src/main/java/de/jalin/ldapadmin/ldap/GroupsDAO.java
Normal file
@ -0,0 +1,125 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.ModificationItem;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import de.jalin.ldapadmin.beans.Group;
|
||||
import de.jalin.ldapadmin.beans.User;
|
||||
|
||||
public class GroupsDAO {
|
||||
|
||||
private final LDAPSession session;
|
||||
|
||||
public GroupsDAO(final LDAPSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public SortedMap<String, Group> loadGroups(final SortedMap<String, User> users) throws LDAPSessionException
|
||||
{
|
||||
final SortedMap<String, Group> list = new TreeMap<String, Group>();
|
||||
final List<SearchResult> searchResult = session.search("ou=groups"); //$NON-NLS-1$
|
||||
for (final SearchResult result : searchResult) {
|
||||
final Attributes attribs = result.getAttributes();
|
||||
final Group grp = new Group();
|
||||
grp.setName(session.getStringValue(attribs, "cn")); //$NON-NLS-1$
|
||||
grp.setDn(result.getNameInNamespace());
|
||||
final List<String> listOfMembers = session.getListOfValues(attribs, "uniqueMember"); //$NON-NLS-1$
|
||||
final String dn = grp.getDn();
|
||||
for (String userDN : listOfMembers) {
|
||||
final User user = users.get(userDN);
|
||||
final List<String> groups = user.getGroups();
|
||||
groups.add(dn);
|
||||
}
|
||||
grp.setMembers(listOfMembers);
|
||||
list.put(dn, grp);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void create(final Group grp) throws LDAPSessionException, AlreadyBoundException {
|
||||
assert grp != null;
|
||||
final String name = grp.getName();
|
||||
assert name != null;
|
||||
final BasicAttributes attributes = new BasicAttributes();
|
||||
final BasicAttribute objClass = new BasicAttribute("objectClass"); //$NON-NLS-1$
|
||||
objClass.add("top"); //$NON-NLS-1$
|
||||
objClass.add("groupOfUniqueNames"); //$NON-NLS-1$
|
||||
attributes.put(objClass);
|
||||
attributes.put("cn", name); //$NON-NLS-1$
|
||||
final List<String> uniqueMembers = grp.getMembers();
|
||||
final BasicAttribute uniqMembers = new BasicAttribute("uniqueMember"); //$NON-NLS-1$
|
||||
if (uniqueMembers != null && uniqueMembers.size() > 0) {
|
||||
for (String dn : uniqueMembers) {
|
||||
uniqMembers.add(dn);
|
||||
}
|
||||
}
|
||||
attributes.put(uniqMembers);
|
||||
final String dn = session.createSubcontext("cn=${cn},ou=groups".replace("${cn}", name), attributes); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
grp.setDn(dn);
|
||||
}
|
||||
|
||||
public Group readGroup(final String dn, final SortedMap<String, User> users) throws LDAPSessionException {
|
||||
final Attributes attribs = session.getAttributes(dn.substring(0, dn.indexOf("ou=groups") + 9)); //$NON-NLS-1$
|
||||
final Group grp = new Group();
|
||||
grp.setDn(dn);
|
||||
grp.setName(session.getStringValue(attribs, "cn")); //$NON-NLS-1$
|
||||
final List<String> listOfMembers = session.getListOfValues(attribs, "uniqueMember"); //$NON-NLS-1$
|
||||
for (String userDN : listOfMembers) {
|
||||
final User user = users.get(userDN);
|
||||
final List<String> groups = user.getGroups();
|
||||
groups.add(dn);
|
||||
}
|
||||
grp.setMembers(listOfMembers);
|
||||
return grp;
|
||||
}
|
||||
|
||||
public void update(final Group grp) throws LDAPSessionException, NoGroupMembersException {
|
||||
assert grp != null;
|
||||
final String name = grp.getName();
|
||||
assert name != null;
|
||||
if (grp.getMembers().size() == 0) {
|
||||
throw new NoGroupMembersException(name);
|
||||
}
|
||||
final BasicAttribute membersOfAttrib = new BasicAttribute("uniqueMember"); //$NON-NLS-1$
|
||||
for (final String memberDN : grp.getMembers()) {
|
||||
membersOfAttrib.add(memberDN);
|
||||
}
|
||||
final ModificationItem modificationItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, membersOfAttrib);
|
||||
session.modifyAttributes("cn=${cn},ou=groups".replace("${cn}", name), new ModificationItem[] { modificationItem }); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
public void updateMemberships(final User usr) throws LDAPSessionException, NoGroupMembersException {
|
||||
final List<SearchResult> searchResult = session.search("ou=groups"); //$NON-NLS-1$
|
||||
for (final SearchResult result : searchResult) {
|
||||
final Attributes attribs = result.getAttributes();
|
||||
final Group grp = new Group();
|
||||
grp.setName(session.getStringValue(attribs, "cn")); //$NON-NLS-1$
|
||||
grp.setDn(result.getNameInNamespace());
|
||||
final List<String> listOfGroupMembers = session.getListOfValues(attribs, "uniqueMember"); //$NON-NLS-1$
|
||||
grp.setMembers(listOfGroupMembers);
|
||||
final List<String> listOfUserMemberships = usr.getGroups();
|
||||
if (listOfGroupMembers.contains(usr.getDn()) && !listOfUserMemberships.contains(grp.getDn())) {
|
||||
grp.getMembers().remove(usr.getDn());
|
||||
update(grp);
|
||||
}
|
||||
if (!listOfGroupMembers.contains(usr.getDn()) && listOfUserMemberships.contains(grp.getDn())) {
|
||||
grp.getMembers().add(usr.getDn());
|
||||
update(grp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(final Group grp) throws LDAPSessionException {
|
||||
assert grp != null;
|
||||
session.unbind("cn=${id},ou=groups", grp.getName()); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
}
|
182
src/main/java/de/jalin/ldapadmin/ldap/LDAPSession.java
Normal file
182
src/main/java/de/jalin/ldapadmin/ldap/LDAPSession.java
Normal file
@ -0,0 +1,182 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NameAlreadyBoundException;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.NoPermissionException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.ModificationItem;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
public class LDAPSession {
|
||||
|
||||
private InitialDirContext ctx;
|
||||
|
||||
public LDAPSession(final String providerURL, final String principal, final String password) throws LDAPSessionException {
|
||||
final Properties env = new Properties();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); //$NON-NLS-1$
|
||||
env.put("com.sun.jndi.ldap.connect.pool", "true"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
env.put(Context.PROVIDER_URL, providerURL);
|
||||
env.put(Context.SECURITY_AUTHENTICATION, "simple"); //$NON-NLS-1$
|
||||
env.put(Context.SECURITY_PRINCIPAL, principal);
|
||||
env.put(Context.SECURITY_CREDENTIALS, password);
|
||||
try {
|
||||
ctx = new InitialDirContext(env);
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
createOrgUnitNodesIfNotExist();
|
||||
}
|
||||
|
||||
public String getStringValue(final Attributes attribs, final String attrName) throws LDAPSessionException {
|
||||
final Attribute attribute = attribs.get(attrName);
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (String) attribute.get();
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBytesValue(final Attributes attribs, final String attrName) throws LDAPSessionException {
|
||||
final Attribute attribute = attribs.get(attrName);
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (byte[]) attribute.get();
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getListOfValues(final Attributes attribs, final String attrName) throws LDAPSessionException {
|
||||
final Attribute attribute = attribs.get(attrName);
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final int size = attribute.size();
|
||||
List<String> listOfValues = new ArrayList<String>();
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
listOfValues.add((String) attribute.get(idx));
|
||||
}
|
||||
return listOfValues;
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String createSubcontext(final String subcontext, final BasicAttributes attributes) throws LDAPSessionException, AlreadyBoundException {
|
||||
try {
|
||||
final DirContext dirContext = ctx.createSubcontext(subcontext, attributes);
|
||||
return dirContext.getNameInNamespace();
|
||||
} catch (NameAlreadyBoundException e) {
|
||||
throw new AlreadyBoundException(subcontext);
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SearchResult> search(final String name, final String attribName, final String attribValue) throws LDAPSessionException {
|
||||
final List<SearchResult> searchResult = new ArrayList<SearchResult>();
|
||||
try {
|
||||
Attributes matchingAttributes = new BasicAttributes();
|
||||
matchingAttributes.put(attribName, attribValue);
|
||||
final NamingEnumeration<SearchResult> searchEnum = ctx.search(name, matchingAttributes);
|
||||
while (searchEnum.hasMore()) {
|
||||
searchResult.add(searchEnum.next());
|
||||
}
|
||||
return searchResult;
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<SearchResult> search(final String name) throws LDAPSessionException {
|
||||
final List<SearchResult> searchResult = new ArrayList<SearchResult>();
|
||||
try {
|
||||
final NamingEnumeration<SearchResult> searchEnum = ctx.search(name, null);
|
||||
while (searchEnum.hasMore()) {
|
||||
searchResult.add(searchEnum.next());
|
||||
}
|
||||
return searchResult;
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Attributes getAttributes(final String dn) throws LDAPSessionException {
|
||||
try {
|
||||
return ctx.getAttributes(dn);
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void modifyAttributes(final String name, final ModificationItem[] mods) throws LDAPSessionException {
|
||||
try {
|
||||
ctx.modifyAttributes(name, mods);
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void unbind(final String searchPattern, final String id) throws LDAPSessionException {
|
||||
try {
|
||||
ctx.unbind(searchPattern.replace("${id}", id)); //$NON-NLS-1$
|
||||
} catch (NamingException e) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws NamingException {
|
||||
if (ctx != null) {
|
||||
ctx.close();
|
||||
ctx = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void createOrgUnitNodesIfNotExist() throws LDAPSessionException {
|
||||
try {
|
||||
final BasicAttributes usersAttributes = new BasicAttributes();
|
||||
final BasicAttribute usersObjClass = new BasicAttribute("objectClass"); //$NON-NLS-1$
|
||||
usersObjClass.add("top"); //$NON-NLS-1$
|
||||
usersObjClass.add("organizationalUnit"); //$NON-NLS-1$
|
||||
usersAttributes.put(usersObjClass);
|
||||
usersAttributes.put("ou", "users"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ctx.createSubcontext("ou=users", usersAttributes); //$NON-NLS-1$
|
||||
} catch (NamingException e) {
|
||||
if (!((e instanceof NameAlreadyBoundException) || (e instanceof NoPermissionException))) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
final BasicAttributes groupsAttributes = new BasicAttributes();
|
||||
final BasicAttribute groupsObjClass = new BasicAttribute("objectClass"); //$NON-NLS-1$
|
||||
groupsObjClass.add("top"); //$NON-NLS-1$
|
||||
groupsObjClass.add("organizationalUnit"); //$NON-NLS-1$
|
||||
groupsAttributes.put(groupsObjClass);
|
||||
groupsAttributes.put("ou", "groups"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ctx.createSubcontext("ou=groups", groupsAttributes); //$NON-NLS-1$
|
||||
} catch (NamingException e) {
|
||||
if (!((e instanceof NameAlreadyBoundException) || (e instanceof NoPermissionException))) {
|
||||
throw new LDAPSessionException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
public class LDAPSessionException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public LDAPSessionException(NamingException e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
public class NoGroupMembersException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String groupName;
|
||||
|
||||
public NoGroupMembersException(final String name) {
|
||||
groupName = name;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
}
|
40
src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java
Normal file
40
src/main/java/de/jalin/ldapadmin/ldap/PasswordValidator.java
Normal file
@ -0,0 +1,40 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
|
||||
public class PasswordValidator {
|
||||
|
||||
private static final int MIN_PASSWORD_LEN = 6;
|
||||
|
||||
public void validate(final String password) throws SimplePasswordException {
|
||||
if (password == null || password.isEmpty()) {
|
||||
throw new SimplePasswordException("password required");
|
||||
}
|
||||
if (password.length() < MIN_PASSWORD_LEN) {
|
||||
throw new SimplePasswordException("minimal password length is " + MIN_PASSWORD_LEN + " characters");
|
||||
}
|
||||
int hasLowerCaseChar = 0;
|
||||
int hasUpperCaseChar = 0;
|
||||
int hasDigits = 0;
|
||||
int hasSpecialChar = 0;
|
||||
for (int idx = 0; idx < password.length(); idx++) {
|
||||
final char test = password.charAt(idx);
|
||||
final int type = Character.getType(test);
|
||||
if (type == Character.DECIMAL_DIGIT_NUMBER) {
|
||||
hasDigits = 1;
|
||||
} else {
|
||||
if (type == Character.LOWERCASE_LETTER) {
|
||||
hasLowerCaseChar = 1;
|
||||
} else
|
||||
if (type == Character.UPPERCASE_LETTER) {
|
||||
hasUpperCaseChar = 1;
|
||||
} else
|
||||
hasSpecialChar = 1;
|
||||
}
|
||||
}
|
||||
if (hasDigits + hasLowerCaseChar + hasUpperCaseChar + hasSpecialChar < 3) {
|
||||
throw new SimplePasswordException("a password requires 3 out of 4 "
|
||||
+ "different character types: lowercase, uppercase, digits and special characters");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
public class RequiredAttributeException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String fieldname;
|
||||
|
||||
public RequiredAttributeException(final String fieldname) {
|
||||
this.fieldname = fieldname;
|
||||
}
|
||||
|
||||
public String getFieldname() {
|
||||
return fieldname;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
public class SimplePasswordException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SimplePasswordException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
168
src/main/java/de/jalin/ldapadmin/ldap/UsersDAO.java
Normal file
168
src/main/java/de/jalin/ldapadmin/ldap/UsersDAO.java
Normal file
@ -0,0 +1,168 @@
|
||||
package de.jalin.ldapadmin.ldap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.ModificationItem;
|
||||
import javax.naming.directory.SearchResult;
|
||||
|
||||
import de.jalin.ldapadmin.beans.User;
|
||||
|
||||
public class UsersDAO {
|
||||
|
||||
private final LDAPSession session;
|
||||
|
||||
public UsersDAO(final LDAPSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public SortedMap<String, User> loadUsers() throws LDAPSessionException
|
||||
{
|
||||
final SortedMap<String, User> usersHash = new TreeMap<String, User>();
|
||||
final List<SearchResult> enumeration = session.search("ou=users"); //$NON-NLS-1$
|
||||
for (SearchResult result : enumeration) {
|
||||
final Attributes attribs = result.getAttributes();
|
||||
final User usr = new User();
|
||||
usr.setFirstname(session.getStringValue(attribs, "givenName")); //$NON-NLS-1$
|
||||
usr.setLastname(session.getStringValue(attribs, "sn")); //$NON-NLS-1$
|
||||
usr.setEmail(session.getStringValue(attribs, "mail")); //$NON-NLS-1$
|
||||
usr.setLogin(session.getStringValue(attribs, "uid")); //$NON-NLS-1$
|
||||
usr.setPhone(session.getStringValue(attribs, "telephoneNumber")); //$NON-NLS-1$
|
||||
usr.setMobile(session.getStringValue(attribs, "mobile")); //$NON-NLS-1$
|
||||
usr.setDisplayname(session.getStringValue(attribs, "displayName")); //$NON-NLS-1$
|
||||
usr.setLogin(session.getStringValue(attribs, "uid")); //$NON-NLS-1$
|
||||
usr.setDn(result.getNameInNamespace());
|
||||
usersHash.put(usr.getDn(), usr);
|
||||
}
|
||||
return usersHash;
|
||||
}
|
||||
|
||||
public void create(final User usr) throws LDAPSessionException, RequiredAttributeException, AlreadyBoundException {
|
||||
assert usr != null;
|
||||
final String uid = usr.getLogin();
|
||||
if (!hasValue(uid)) {
|
||||
throw new RequiredAttributeException("uid"); //$NON-NLS-1$
|
||||
}
|
||||
assert uid != null;
|
||||
final BasicAttributes attributes = new BasicAttributes();
|
||||
final BasicAttribute objClass = new BasicAttribute("objectClass"); //$NON-NLS-1$
|
||||
objClass.add("top"); //$NON-NLS-1$
|
||||
objClass.add("person"); //$NON-NLS-1$
|
||||
objClass.add("organizationalPerson"); //$NON-NLS-1$
|
||||
objClass.add("inetOrgPerson"); //$NON-NLS-1$
|
||||
attributes.put(objClass);
|
||||
final String firstName = usr.getFirstname();
|
||||
if (hasValue(firstName)) {
|
||||
attributes.put("givenName", firstName); //$NON-NLS-1$
|
||||
}
|
||||
final String lastname = usr.getLastname();
|
||||
if (!hasValue(lastname)) {
|
||||
throw new RequiredAttributeException("lastname"); //$NON-NLS-1$
|
||||
}
|
||||
attributes.put("sn", lastname); //$NON-NLS-1$
|
||||
final String email = usr.getEmail();
|
||||
if (hasValue(email)) {
|
||||
attributes.put("mail", email); //$NON-NLS-1$
|
||||
}
|
||||
attributes.put("uid", uid); //$NON-NLS-1$
|
||||
attributes.put("cn", uid); //$NON-NLS-1$
|
||||
final String telephone = usr.getPhone();
|
||||
if (hasValue(telephone)) {
|
||||
attributes.put("telephoneNumber", telephone); //$NON-NLS-1$
|
||||
}
|
||||
final String mobile = usr.getMobile();
|
||||
if (hasValue(mobile)) {
|
||||
attributes.put("mobile", mobile); //$NON-NLS-1$
|
||||
}
|
||||
final String comment = usr.getDisplayname();
|
||||
if (hasValue(comment)) {
|
||||
attributes.put("displayName", comment); //$NON-NLS-1$
|
||||
} else {
|
||||
attributes.put("displayName", firstName == null ? lastname : lastname + ", " + firstName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
final String password = usr.getPassword();
|
||||
if (!hasValue(password)) {
|
||||
throw new RequiredAttributeException("password"); //$NON-NLS-1$
|
||||
}
|
||||
attributes.put("userPassword", password); //$NON-NLS-1$
|
||||
final String dn = session.createSubcontext("uid=${uid},ou=users".replace("${uid}", uid), attributes); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
usr.setDn(dn);
|
||||
}
|
||||
|
||||
public User read(final String dn) throws LDAPSessionException {
|
||||
final Attributes attribs = session.getAttributes(dn.substring(0, dn.indexOf("ou=users") + 8)); //$NON-NLS-1$
|
||||
final User usr = new User();
|
||||
usr.setFirstname(session.getStringValue(attribs, "givenName")); //$NON-NLS-1$
|
||||
usr.setLastname(session.getStringValue(attribs, "sn")); //$NON-NLS-1$
|
||||
usr.setEmail(session.getStringValue(attribs, "mail")); //$NON-NLS-1$
|
||||
usr.setLogin(session.getStringValue(attribs, "uid")); //$NON-NLS-1$
|
||||
usr.setPhone(session.getStringValue(attribs, "telephoneNumber")); //$NON-NLS-1$
|
||||
usr.setMobile(session.getStringValue(attribs, "mobile")); //$NON-NLS-1$
|
||||
usr.setDisplayname(session.getStringValue(attribs, "displayName")); //$NON-NLS-1$
|
||||
usr.setLogin(session.getStringValue(attribs, "uid")); //$NON-NLS-1$
|
||||
usr.setDn(dn);
|
||||
return usr;
|
||||
}
|
||||
|
||||
public void update(final User usr) throws LDAPSessionException {
|
||||
assert usr != null;
|
||||
final String uid = usr.getLogin();
|
||||
assert uid != null;
|
||||
final Attributes attribs = session.getAttributes(
|
||||
"uid=${uid},ou=users".replace("${uid}", uid)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
final List<ModificationItem> updates = new ArrayList<ModificationItem>();
|
||||
addStringAttrUpdate(updates, attribs, "displayName", usr.getDisplayname()); //$NON-NLS-1$
|
||||
addStringAttrUpdate(updates, attribs, "mail", usr.getEmail()); //$NON-NLS-1$
|
||||
addStringAttrUpdate(updates, attribs, "givenName", usr.getFirstname()); //$NON-NLS-1$
|
||||
addStringAttrUpdate(updates, attribs, "sn", usr.getLastname()); //$NON-NLS-1$
|
||||
addStringAttrUpdate(updates, attribs, "mobile", usr.getMobile()); //$NON-NLS-1$
|
||||
addStringAttrUpdate(updates, attribs, "telephoneNumber", usr.getPhone()); //$NON-NLS-1$
|
||||
addPasswordUpdate(updates, "userPassword", usr.getPassword()); //$NON-NLS-1$
|
||||
session.modifyAttributes("uid=${uid},ou=users".replace("${uid}", uid), updates.toArray(new ModificationItem[] { })); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
public void delete(final User user) throws LDAPSessionException {
|
||||
assert user != null;
|
||||
session.unbind("uid=${id},ou=users", user.getLogin()); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private boolean hasValue(final String email) {
|
||||
return email != null && !email.isEmpty();
|
||||
}
|
||||
|
||||
private void addStringAttrUpdate(final List<ModificationItem> updates,
|
||||
final Attributes attribs, final String attributeName, final String newValue) throws LDAPSessionException {
|
||||
final String oldValue = session.getStringValue(attribs, attributeName);
|
||||
final BasicAttribute basicAttribute = new BasicAttribute(attributeName);
|
||||
if (hasValue(newValue)) {
|
||||
if (!newValue.equals(oldValue)) {
|
||||
basicAttribute.add(newValue);
|
||||
int ldapOp = DirContext.REPLACE_ATTRIBUTE;
|
||||
if (oldValue == null) {
|
||||
ldapOp = DirContext.ADD_ATTRIBUTE;
|
||||
}
|
||||
final ModificationItem modificationItem = new ModificationItem(ldapOp, basicAttribute);
|
||||
updates.add(modificationItem);
|
||||
}
|
||||
} else {
|
||||
if (hasValue(oldValue)) {
|
||||
updates.add(new ModificationItem(DirContext.REMOVE_ATTRIBUTE, basicAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPasswordUpdate(final List<ModificationItem> updates,
|
||||
final String attributeName, final String newValue) throws LDAPSessionException {
|
||||
if (hasValue(newValue)) {
|
||||
updates.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
|
||||
new BasicAttribute(attributeName, newValue)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package de.jalin.ldapadmin.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import de.jalin.ldapadmin.beans.Group;
|
||||
import de.jalin.ldapadmin.beans.User;
|
||||
import de.jalin.ldapadmin.ldap.LDAPSession;
|
||||
import de.jalin.ldapadmin.ldap.LDAPSessionException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class AbstractLDAPServlet extends HttpServlet {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final Logger LOG = Logger.getLogger("LDAP");
|
||||
|
||||
private SortedMap<String, User> users;
|
||||
private SortedMap<String, Group> groups;
|
||||
|
||||
protected LDAPSession ldapSession;
|
||||
protected Properties config;
|
||||
|
||||
protected void loadData() {
|
||||
users = new TreeMap<>();
|
||||
groups = new TreeMap<>();
|
||||
}
|
||||
|
||||
protected User getUser(final String uid) {
|
||||
return users.get(uid);
|
||||
}
|
||||
|
||||
protected Group getGroup(final String gid) {
|
||||
return groups.get(gid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
final InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties"); //$NON-NLS-1$
|
||||
config = new Properties();
|
||||
try {
|
||||
config.load(inputStream);
|
||||
ldapSession = new LDAPSession(config.getProperty("provider.url"), config.getProperty("security.principal"), config.getProperty("security.password")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
} catch (IOException | LDAPSessionException e) {
|
||||
LOG.severe(e.getMessage());
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
try {
|
||||
ldapSession.close();
|
||||
} catch (NamingException e) {
|
||||
LOG.severe(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void throwServletException(final HttpSession session, final Exception e) throws ServletException
|
||||
{
|
||||
session.setAttribute("servletexception", e); //$NON-NLS-1$
|
||||
LOG.severe(e.getMessage());
|
||||
throw new ServletException(e);
|
||||
}
|
||||
|
||||
protected void cleanSession(final HttpSession httpSession) {
|
||||
httpSession.removeAttribute("errormessage"); //$NON-NLS-1$
|
||||
httpSession.removeAttribute(" |