mirror of
				https://github.com/nitnelave/lldap.git
				synced 2023-04-12 14:25:13 +00:00 
			
		
		
		
	Merge branch 'main' into feature/dark-theme
This commit is contained in:
		
						commit
						fbbe56a974
					
				
							
								
								
									
										7
									
								
								.github/workflows/Dockerfile.ci.alpine
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/workflows/Dockerfile.ci.alpine
									
									
									
									
										vendored
									
									
								
							@ -12,8 +12,10 @@ RUN mkdir -p /lldap/app
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
				
			||||||
    mv bin/x86_64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/x86_64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/x86_64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -21,8 +23,10 @@ RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
				
			||||||
    mv bin/aarch64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/aarch64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/aarch64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -30,8 +34,10 @@ RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm/v7" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/arm/v7" ]; then \
 | 
				
			||||||
    mv bin/armv7-unknown-linux-gnueabihf-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -42,6 +48,7 @@ COPY lldap_config.docker_template.toml /lldap/
 | 
				
			|||||||
COPY web/index_local.html web/index.html
 | 
					COPY web/index_local.html web/index.html
 | 
				
			||||||
RUN cp target/lldap /lldap/ && \
 | 
					RUN cp target/lldap /lldap/ && \
 | 
				
			||||||
    cp target/migration-tool /lldap/ && \
 | 
					    cp target/migration-tool /lldap/ && \
 | 
				
			||||||
 | 
					    cp target/lldap_set_password /lldap/ && \
 | 
				
			||||||
    cp -R web/index.html \
 | 
					    cp -R web/index.html \
 | 
				
			||||||
          web/pkg \
 | 
					          web/pkg \
 | 
				
			||||||
          web/static \
 | 
					          web/static \
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								.github/workflows/Dockerfile.ci.debian
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/workflows/Dockerfile.ci.debian
									
									
									
									
										vendored
									
									
								
							@ -12,8 +12,10 @@ RUN mkdir -p /lldap/app
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
				
			||||||
    mv bin/x86_64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/x86_64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/x86_64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -21,8 +23,10 @@ RUN if [ "${TARGETPLATFORM}" = "linux/amd64" ]; then \
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
				
			||||||
    mv bin/aarch64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/aarch64-unknown-linux-musl-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/aarch64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -30,8 +34,10 @@ RUN if [ "${TARGETPLATFORM}" = "linux/arm64" ]; then \
 | 
				
			|||||||
RUN if [ "${TARGETPLATFORM}" = "linux/arm/v7" ]; then \
 | 
					RUN if [ "${TARGETPLATFORM}" = "linux/arm/v7" ]; then \
 | 
				
			||||||
    mv bin/armv7-unknown-linux-gnueabihf-lldap-bin/lldap target/lldap && \
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-lldap-bin/lldap target/lldap && \
 | 
				
			||||||
    mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool target/migration-tool && \
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool target/migration-tool && \
 | 
				
			||||||
 | 
					    mv bin/armv7-unknown-linux-gnueabihf-lldap_set_password-bin/lldap_set_password target/lldap_set_password && \
 | 
				
			||||||
    chmod +x target/lldap && \
 | 
					    chmod +x target/lldap && \
 | 
				
			||||||
    chmod +x target/migration-tool && \
 | 
					    chmod +x target/migration-tool && \
 | 
				
			||||||
 | 
					    chmod +x target/lldap_set_password && \
 | 
				
			||||||
    ls -la target/ . && \
 | 
					    ls -la target/ . && \
 | 
				
			||||||
    pwd \
 | 
					    pwd \
 | 
				
			||||||
    ; fi
 | 
					    ; fi
 | 
				
			||||||
@ -42,6 +48,7 @@ COPY lldap_config.docker_template.toml /lldap/
 | 
				
			|||||||
COPY web/index_local.html web/index.html
 | 
					COPY web/index_local.html web/index.html
 | 
				
			||||||
RUN cp target/lldap /lldap/ && \
 | 
					RUN cp target/lldap /lldap/ && \
 | 
				
			||||||
    cp target/migration-tool /lldap/ && \
 | 
					    cp target/migration-tool /lldap/ && \
 | 
				
			||||||
 | 
					    cp target/lldap_set_password /lldap/ && \
 | 
				
			||||||
    cp -R web/index.html \
 | 
					    cp -R web/index.html \
 | 
				
			||||||
          web/pkg \
 | 
					          web/pkg \
 | 
				
			||||||
          web/static \
 | 
					          web/static \
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								.github/workflows/docker-build-static.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/docker-build-static.yml
									
									
									
									
										vendored
									
									
								
							@ -125,8 +125,8 @@ jobs:
 | 
				
			|||||||
          key: lldap-bin-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
 | 
					          key: lldap-bin-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
 | 
				
			||||||
          restore-keys: |
 | 
					          restore-keys: |
 | 
				
			||||||
            lldap-bin-${{ matrix.target }}-
 | 
					            lldap-bin-${{ matrix.target }}-
 | 
				
			||||||
      - name: Compile ${{ matrix.target }} lldap and migration tool
 | 
					      - name: Compile ${{ matrix.target }} lldap and tools
 | 
				
			||||||
        run: cargo build --target=${{ matrix.target }} --release -p lldap -p migration-tool
 | 
					        run: cargo build --target=${{ matrix.target }} --release -p lldap -p migration-tool -p lldap_set_password
 | 
				
			||||||
      - name: Check path
 | 
					      - name: Check path
 | 
				
			||||||
        run: ls -al target/release
 | 
					        run: ls -al target/release
 | 
				
			||||||
      - name: Upload ${{ matrix.target}} lldap artifacts
 | 
					      - name: Upload ${{ matrix.target}} lldap artifacts
 | 
				
			||||||
@ -139,6 +139,11 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          name: ${{ matrix.target }}-migration-tool-bin
 | 
					          name: ${{ matrix.target }}-migration-tool-bin
 | 
				
			||||||
          path: target/${{ matrix.target }}/release/migration-tool
 | 
					          path: target/${{ matrix.target }}/release/migration-tool
 | 
				
			||||||
 | 
					      - name: Upload ${{ matrix.target }} password tool artifacts
 | 
				
			||||||
 | 
					        uses: actions/upload-artifact@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          name: ${{ matrix.target }}-lldap_set_password-bin
 | 
				
			||||||
 | 
					          path: target/${{ matrix.target }}/release/lldap_set_password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  lldap-database-integration-test:
 | 
					  lldap-database-integration-test:
 | 
				
			||||||
    needs: [build-ui,build-bin]
 | 
					    needs: [build-ui,build-bin]
 | 
				
			||||||
@ -347,8 +352,12 @@ jobs:
 | 
				
			|||||||
             mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool bin/aarch64-migration-tool
 | 
					             mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool bin/aarch64-migration-tool
 | 
				
			||||||
             mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool bin/amd64-migration-tool
 | 
					             mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool bin/amd64-migration-tool
 | 
				
			||||||
             mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool bin/armhf-migration-tool
 | 
					             mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool bin/armhf-migration-tool
 | 
				
			||||||
 | 
					             mv bin/aarch64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password bin/aarch64-lldap_set_password
 | 
				
			||||||
 | 
					             mv bin/x86_64-unknown-linux-musl-lldap_set_password-bin/lldap_set_password bin/amd64-lldap_set_password
 | 
				
			||||||
 | 
					             mv bin/armv7-unknown-linux-gnueabihf-lldap_set_password-bin/lldap_set_password bin/armhf-lldap_set_password
 | 
				
			||||||
             chmod +x bin/*-lldap
 | 
					             chmod +x bin/*-lldap
 | 
				
			||||||
             chmod +x bin/*-migration-tool
 | 
					             chmod +x bin/*-migration-tool
 | 
				
			||||||
 | 
					             chmod +x bin/*-lldap_set_password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Download llap ui artifacts
 | 
					      - name: Download llap ui artifacts
 | 
				
			||||||
        uses: actions/download-artifact@v3
 | 
					        uses: actions/download-artifact@v3
 | 
				
			||||||
@ -376,6 +385,9 @@ jobs:
 | 
				
			|||||||
             mv bin/aarch64-migration-tool aarch64-lldap/migration-tool
 | 
					             mv bin/aarch64-migration-tool aarch64-lldap/migration-tool
 | 
				
			||||||
             mv bin/amd64-migration-tool amd64-lldap/migration-tool
 | 
					             mv bin/amd64-migration-tool amd64-lldap/migration-tool
 | 
				
			||||||
             mv bin/armhf-migration-tool armhf-lldap/migration-tool
 | 
					             mv bin/armhf-migration-tool armhf-lldap/migration-tool
 | 
				
			||||||
 | 
					             mv bin/aarch64-lldap_set_password aarch64-lldap/lldap_set_password
 | 
				
			||||||
 | 
					             mv bin/amd64-lldap_set_password amd64-lldap/lldap_set_password
 | 
				
			||||||
 | 
					             mv bin/armhf-lldap_set_password armhf-lldap/lldap_set_password
 | 
				
			||||||
             cp -r app aarch64-lldap/
 | 
					             cp -r app aarch64-lldap/
 | 
				
			||||||
             cp -r app amd64-lldap/
 | 
					             cp -r app amd64-lldap/
 | 
				
			||||||
             cp -r app armhf-lldap/
 | 
					             cp -r app armhf-lldap/
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -2456,6 +2456,19 @@ dependencies = [
 | 
				
			|||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "lldap_set_password"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "anyhow",
 | 
				
			||||||
 | 
					 "clap",
 | 
				
			||||||
 | 
					 "lldap_auth",
 | 
				
			||||||
 | 
					 "rand 0.8.5",
 | 
				
			||||||
 | 
					 "reqwest",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "serde_json",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "local-channel"
 | 
					name = "local-channel"
 | 
				
			||||||
version = "0.1.3"
 | 
					version = "0.1.3"
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,8 @@ members = [
 | 
				
			|||||||
  "server",
 | 
					  "server",
 | 
				
			||||||
  "auth",
 | 
					  "auth",
 | 
				
			||||||
  "app",
 | 
					  "app",
 | 
				
			||||||
  "migration-tool"
 | 
					  "migration-tool",
 | 
				
			||||||
 | 
					  "set-password",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
default-members = ["server"]
 | 
					default-members = ["server"]
 | 
				
			||||||
 | 
				
			|||||||
@ -31,11 +31,12 @@ FROM chef AS builder
 | 
				
			|||||||
COPY --from=planner /tmp/recipe.json recipe.json
 | 
					COPY --from=planner /tmp/recipe.json recipe.json
 | 
				
			||||||
RUN cargo chef cook --release -p lldap_app --target wasm32-unknown-unknown \
 | 
					RUN cargo chef cook --release -p lldap_app --target wasm32-unknown-unknown \
 | 
				
			||||||
    && cargo chef cook --release -p lldap \
 | 
					    && cargo chef cook --release -p lldap \
 | 
				
			||||||
    && cargo chef cook --release -p migration-tool
 | 
					    && cargo chef cook --release -p migration-tool \
 | 
				
			||||||
 | 
					    && cargo chef cook --release -p lldap_set_password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Copy the source and build the app and server.
 | 
					# Copy the source and build the app and server.
 | 
				
			||||||
COPY --chown=app:app . .
 | 
					COPY --chown=app:app . .
 | 
				
			||||||
RUN cargo build --release -p lldap -p migration-tool \
 | 
					RUN cargo build --release -p lldap -p migration-tool -p lldap_set_password \
 | 
				
			||||||
    # Build the frontend.
 | 
					    # Build the frontend.
 | 
				
			||||||
    && ./app/build.sh
 | 
					    && ./app/build.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,7 +78,7 @@ WORKDIR /app
 | 
				
			|||||||
COPY --from=builder /app/app/index_local.html app/index.html
 | 
					COPY --from=builder /app/app/index_local.html app/index.html
 | 
				
			||||||
COPY --from=builder /app/app/static app/static
 | 
					COPY --from=builder /app/app/static app/static
 | 
				
			||||||
COPY --from=builder /app/app/pkg app/pkg
 | 
					COPY --from=builder /app/app/pkg app/pkg
 | 
				
			||||||
COPY --from=builder /app/target/release/lldap /app/target/release/migration-tool ./
 | 
					COPY --from=builder /app/target/release/lldap /app/target/release/migration-tool /app/target/release/lldap_set_password ./
 | 
				
			||||||
COPY docker-entrypoint.sh lldap_config.docker_template.toml ./
 | 
					COPY docker-entrypoint.sh lldap_config.docker_template.toml ./
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN set -x \
 | 
					RUN set -x \
 | 
				
			||||||
 | 
				
			|||||||
@ -45,11 +45,7 @@ pub fn get_user_attribute(
 | 
				
			|||||||
            .into_iter()
 | 
					            .into_iter()
 | 
				
			||||||
            .flatten()
 | 
					            .flatten()
 | 
				
			||||||
            .map(|id_and_name| {
 | 
					            .map(|id_and_name| {
 | 
				
			||||||
                format!(
 | 
					                format!("cn={},ou=groups,{}", &id_and_name.display_name, base_dn_str).into_bytes()
 | 
				
			||||||
                    "uid={},ou=groups,{}",
 | 
					 | 
				
			||||||
                    &id_and_name.display_name, base_dn_str
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .into_bytes()
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .collect(),
 | 
					            .collect(),
 | 
				
			||||||
        "cn" | "displayname" => vec![user.display_name.clone()?.into_bytes()],
 | 
					        "cn" | "displayname" => vec![user.display_name.clone()?.into_bytes()],
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ use tracing::{info, instrument, warn};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use super::sql_tables::LAST_SCHEMA_VERSION;
 | 
					use super::sql_tables::LAST_SCHEMA_VERSION;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Iden, PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
 | 
					#[derive(Iden, PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Copy)]
 | 
				
			||||||
pub enum Users {
 | 
					pub enum Users {
 | 
				
			||||||
    Table,
 | 
					    Table,
 | 
				
			||||||
    UserId,
 | 
					    UserId,
 | 
				
			||||||
@ -27,7 +27,7 @@ pub enum Users {
 | 
				
			|||||||
    Uuid,
 | 
					    Uuid,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Iden, PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
 | 
					#[derive(Iden, PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Copy)]
 | 
				
			||||||
pub enum Groups {
 | 
					pub enum Groups {
 | 
				
			||||||
    Table,
 | 
					    Table,
 | 
				
			||||||
    GroupId,
 | 
					    GroupId,
 | 
				
			||||||
@ -36,7 +36,7 @@ pub enum Groups {
 | 
				
			|||||||
    Uuid,
 | 
					    Uuid,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Iden)]
 | 
					#[derive(Iden, Clone, Copy)]
 | 
				
			||||||
pub enum Memberships {
 | 
					pub enum Memberships {
 | 
				
			||||||
    Table,
 | 
					    Table,
 | 
				
			||||||
    UserId,
 | 
					    UserId,
 | 
				
			||||||
@ -334,6 +334,132 @@ pub async fn upgrade_to_v1(pool: &DbConnection) -> std::result::Result<(), sea_o
 | 
				
			|||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn replace_column<I: Iden + Copy + 'static, const N: usize>(
 | 
				
			||||||
 | 
					    pool: &DbConnection,
 | 
				
			||||||
 | 
					    table_name: I,
 | 
				
			||||||
 | 
					    column_name: I,
 | 
				
			||||||
 | 
					    mut new_column: ColumnDef,
 | 
				
			||||||
 | 
					    update_values: [Statement; N],
 | 
				
			||||||
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    // Update the definition of a column (in a compatible way). Due to Sqlite, this is more complicated:
 | 
				
			||||||
 | 
					    //  - rename the column to a temporary name
 | 
				
			||||||
 | 
					    //  - create the column with the new definition
 | 
				
			||||||
 | 
					    //  - copy the data from the temp column to the new one
 | 
				
			||||||
 | 
					    //  - update the new one if there are changes needed
 | 
				
			||||||
 | 
					    //  - drop the old one
 | 
				
			||||||
 | 
					    let builder = pool.get_database_backend();
 | 
				
			||||||
 | 
					    pool.transaction::<_, (), sea_orm::DbErr>(move |transaction| {
 | 
				
			||||||
 | 
					        Box::pin(async move {
 | 
				
			||||||
 | 
					            #[derive(Iden)]
 | 
				
			||||||
 | 
					            enum TempTable {
 | 
				
			||||||
 | 
					                TempName,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            transaction
 | 
				
			||||||
 | 
					                .execute(
 | 
				
			||||||
 | 
					                    builder.build(
 | 
				
			||||||
 | 
					                        Table::alter()
 | 
				
			||||||
 | 
					                            .table(table_name)
 | 
				
			||||||
 | 
					                            .rename_column(column_name, TempTable::TempName),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .await?;
 | 
				
			||||||
 | 
					            transaction
 | 
				
			||||||
 | 
					                .execute(
 | 
				
			||||||
 | 
					                    builder.build(Table::alter().table(table_name).add_column(&mut new_column)),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .await?;
 | 
				
			||||||
 | 
					            transaction
 | 
				
			||||||
 | 
					                .execute(
 | 
				
			||||||
 | 
					                    builder.build(
 | 
				
			||||||
 | 
					                        Query::update()
 | 
				
			||||||
 | 
					                            .table(table_name)
 | 
				
			||||||
 | 
					                            .value(column_name, Expr::col((table_name, TempTable::TempName))),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .await?;
 | 
				
			||||||
 | 
					            for statement in update_values {
 | 
				
			||||||
 | 
					                transaction.execute(statement).await?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            transaction
 | 
				
			||||||
 | 
					                .execute(
 | 
				
			||||||
 | 
					                    builder.build(
 | 
				
			||||||
 | 
					                        Table::alter()
 | 
				
			||||||
 | 
					                            .table(table_name)
 | 
				
			||||||
 | 
					                            .drop_column(TempTable::TempName),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .await?;
 | 
				
			||||||
 | 
					            Ok(())
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn migrate_to_v2(pool: &DbConnection) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let builder = pool.get_database_backend();
 | 
				
			||||||
 | 
					    // Allow nulls in DisplayName, and change empty string to null.
 | 
				
			||||||
 | 
					    replace_column(
 | 
				
			||||||
 | 
					        pool,
 | 
				
			||||||
 | 
					        Users::Table,
 | 
				
			||||||
 | 
					        Users::DisplayName,
 | 
				
			||||||
 | 
					        ColumnDef::new(Users::DisplayName)
 | 
				
			||||||
 | 
					            .string_len(255)
 | 
				
			||||||
 | 
					            .to_owned(),
 | 
				
			||||||
 | 
					        [builder.build(
 | 
				
			||||||
 | 
					            Query::update()
 | 
				
			||||||
 | 
					                .table(Users::Table)
 | 
				
			||||||
 | 
					                .value(Users::DisplayName, Option::<String>::None)
 | 
				
			||||||
 | 
					                .cond_where(Expr::col(Users::DisplayName).eq("")),
 | 
				
			||||||
 | 
					        )],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn migrate_to_v3(pool: &DbConnection) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    let builder = pool.get_database_backend();
 | 
				
			||||||
 | 
					    // Allow nulls in First and LastName. Users who created their DB in 0.4.1 have the not null constraint.
 | 
				
			||||||
 | 
					    replace_column(
 | 
				
			||||||
 | 
					        pool,
 | 
				
			||||||
 | 
					        Users::Table,
 | 
				
			||||||
 | 
					        Users::FirstName,
 | 
				
			||||||
 | 
					        ColumnDef::new(Users::FirstName).string_len(255).to_owned(),
 | 
				
			||||||
 | 
					        [builder.build(
 | 
				
			||||||
 | 
					            Query::update()
 | 
				
			||||||
 | 
					                .table(Users::Table)
 | 
				
			||||||
 | 
					                .value(Users::FirstName, Option::<String>::None)
 | 
				
			||||||
 | 
					                .cond_where(Expr::col(Users::FirstName).eq("")),
 | 
				
			||||||
 | 
					        )],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    replace_column(
 | 
				
			||||||
 | 
					        pool,
 | 
				
			||||||
 | 
					        Users::Table,
 | 
				
			||||||
 | 
					        Users::LastName,
 | 
				
			||||||
 | 
					        ColumnDef::new(Users::LastName).string_len(255).to_owned(),
 | 
				
			||||||
 | 
					        [builder.build(
 | 
				
			||||||
 | 
					            Query::update()
 | 
				
			||||||
 | 
					                .table(Users::Table)
 | 
				
			||||||
 | 
					                .value(Users::LastName, Option::<String>::None)
 | 
				
			||||||
 | 
					                .cond_where(Expr::col(Users::LastName).eq("")),
 | 
				
			||||||
 | 
					        )],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    // Change Avatar from binary to blob(long), because for MySQL this is 64kb.
 | 
				
			||||||
 | 
					    replace_column(
 | 
				
			||||||
 | 
					        pool,
 | 
				
			||||||
 | 
					        Users::Table,
 | 
				
			||||||
 | 
					        Users::Avatar,
 | 
				
			||||||
 | 
					        ColumnDef::new(Users::Avatar)
 | 
				
			||||||
 | 
					            .blob(sea_query::BlobSize::Long)
 | 
				
			||||||
 | 
					            .to_owned(),
 | 
				
			||||||
 | 
					        [],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .await?;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn migrate_from_version(
 | 
					pub async fn migrate_from_version(
 | 
				
			||||||
    pool: &DbConnection,
 | 
					    pool: &DbConnection,
 | 
				
			||||||
    version: SchemaVersion,
 | 
					    version: SchemaVersion,
 | 
				
			||||||
@ -346,68 +472,13 @@ pub async fn migrate_from_version(
 | 
				
			|||||||
        std::cmp::Ordering::Equal => return Ok(()),
 | 
					        std::cmp::Ordering::Equal => return Ok(()),
 | 
				
			||||||
        std::cmp::Ordering::Greater => anyhow::bail!("DB version downgrading is not supported"),
 | 
					        std::cmp::Ordering::Greater => anyhow::bail!("DB version downgrading is not supported"),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let builder = pool.get_database_backend();
 | 
					 | 
				
			||||||
    if version < SchemaVersion(2) {
 | 
					    if version < SchemaVersion(2) {
 | 
				
			||||||
        // Drop the not_null constraint on display_name. Due to Sqlite, this is more complicated:
 | 
					        migrate_to_v2(pool).await?;
 | 
				
			||||||
        //  - rename the display_name column to a temporary name
 | 
					 | 
				
			||||||
        //  - create the display_name column without the constraint
 | 
					 | 
				
			||||||
        //  - copy the data from the temp column to the new one
 | 
					 | 
				
			||||||
        //  - update the new one to replace empty strings with null
 | 
					 | 
				
			||||||
        //  - drop the old one
 | 
					 | 
				
			||||||
        pool.transaction::<_, (), sea_orm::DbErr>(|transaction| {
 | 
					 | 
				
			||||||
            Box::pin(async move {
 | 
					 | 
				
			||||||
                #[derive(Iden)]
 | 
					 | 
				
			||||||
                enum TempUsers {
 | 
					 | 
				
			||||||
                    TempDisplayName,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
                transaction
 | 
					    if version < SchemaVersion(3) {
 | 
				
			||||||
                    .execute(
 | 
					        migrate_to_v3(pool).await?;
 | 
				
			||||||
                        builder.build(
 | 
					 | 
				
			||||||
                            Table::alter()
 | 
					 | 
				
			||||||
                                .table(Users::Table)
 | 
					 | 
				
			||||||
                                .rename_column(Users::DisplayName, TempUsers::TempDisplayName),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .await?;
 | 
					 | 
				
			||||||
                transaction
 | 
					 | 
				
			||||||
                    .execute(
 | 
					 | 
				
			||||||
                        builder.build(
 | 
					 | 
				
			||||||
                            Table::alter()
 | 
					 | 
				
			||||||
                                .table(Users::Table)
 | 
					 | 
				
			||||||
                                .add_column(ColumnDef::new(Users::DisplayName).string_len(255)),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .await?;
 | 
					 | 
				
			||||||
                transaction
 | 
					 | 
				
			||||||
                    .execute(builder.build(Query::update().table(Users::Table).value(
 | 
					 | 
				
			||||||
                        Users::DisplayName,
 | 
					 | 
				
			||||||
                        Expr::col((Users::Table, TempUsers::TempDisplayName)),
 | 
					 | 
				
			||||||
                    )))
 | 
					 | 
				
			||||||
                    .await?;
 | 
					 | 
				
			||||||
                transaction
 | 
					 | 
				
			||||||
                    .execute(
 | 
					 | 
				
			||||||
                        builder.build(
 | 
					 | 
				
			||||||
                            Query::update()
 | 
					 | 
				
			||||||
                                .table(Users::Table)
 | 
					 | 
				
			||||||
                                .value(Users::DisplayName, Option::<String>::None)
 | 
					 | 
				
			||||||
                                .cond_where(Expr::col(Users::DisplayName).eq("")),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .await?;
 | 
					 | 
				
			||||||
                transaction
 | 
					 | 
				
			||||||
                    .execute(
 | 
					 | 
				
			||||||
                        builder.build(
 | 
					 | 
				
			||||||
                            Table::alter()
 | 
					 | 
				
			||||||
                                .table(Users::Table)
 | 
					 | 
				
			||||||
                                .drop_column(TempUsers::TempDisplayName),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .await?;
 | 
					 | 
				
			||||||
                Ok(())
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .await?;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    let builder = pool.get_database_backend();
 | 
				
			||||||
    pool.execute(
 | 
					    pool.execute(
 | 
				
			||||||
        builder.build(
 | 
					        builder.build(
 | 
				
			||||||
            Query::update()
 | 
					            Query::update()
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ impl From<SchemaVersion> for Value {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const LAST_SCHEMA_VERSION: SchemaVersion = SchemaVersion(2);
 | 
					pub const LAST_SCHEMA_VERSION: SchemaVersion = SchemaVersion(3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn init_table(pool: &DbConnection) -> anyhow::Result<()> {
 | 
					pub async fn init_table(pool: &DbConnection) -> anyhow::Result<()> {
 | 
				
			||||||
    let version = {
 | 
					    let version = {
 | 
				
			||||||
@ -100,21 +100,21 @@ mod tests {
 | 
				
			|||||||
        let sql_pool = get_in_memory_db().await;
 | 
					        let sql_pool = get_in_memory_db().await;
 | 
				
			||||||
        sql_pool
 | 
					        sql_pool
 | 
				
			||||||
            .execute(raw_statement(
 | 
					            .execute(raw_statement(
 | 
				
			||||||
                r#"CREATE TABLE users ( user_id TEXT, display_name TEXT, creation_date TEXT);"#,
 | 
					                r#"CREATE TABLE users ( user_id TEXT, display_name TEXT, first_name TEXT NOT NULL, last_name TEXT, avatar BLOB, creation_date TEXT);"#,
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
        sql_pool
 | 
					        sql_pool
 | 
				
			||||||
            .execute(raw_statement(
 | 
					            .execute(raw_statement(
 | 
				
			||||||
                r#"INSERT INTO users (user_id, display_name, creation_date)
 | 
					                r#"INSERT INTO users (user_id, display_name, first_name, creation_date)
 | 
				
			||||||
                       VALUES ("bôb", "", "1970-01-01 00:00:00")"#,
 | 
					                       VALUES ("bôb", "", "", "1970-01-01 00:00:00")"#,
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
        sql_pool
 | 
					        sql_pool
 | 
				
			||||||
            .execute(raw_statement(
 | 
					            .execute(raw_statement(
 | 
				
			||||||
                r#"INSERT INTO users (user_id, display_name, creation_date)
 | 
					                r#"INSERT INTO users (user_id, display_name, first_name, creation_date)
 | 
				
			||||||
                       VALUES ("john", "John Doe", "1971-01-01 00:00:00")"#,
 | 
					                       VALUES ("john", "John Doe", "John", "1971-01-01 00:00:00")"#,
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
@ -142,11 +142,12 @@ mod tests {
 | 
				
			|||||||
        #[derive(FromQueryResult, PartialEq, Eq, Debug)]
 | 
					        #[derive(FromQueryResult, PartialEq, Eq, Debug)]
 | 
				
			||||||
        struct SimpleUser {
 | 
					        struct SimpleUser {
 | 
				
			||||||
            display_name: Option<String>,
 | 
					            display_name: Option<String>,
 | 
				
			||||||
 | 
					            first_name: Option<String>,
 | 
				
			||||||
            uuid: Uuid,
 | 
					            uuid: Uuid,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
            SimpleUser::find_by_statement(raw_statement(
 | 
					            SimpleUser::find_by_statement(raw_statement(
 | 
				
			||||||
                r#"SELECT display_name, uuid FROM users ORDER BY display_name"#
 | 
					                r#"SELECT display_name, first_name, uuid FROM users ORDER BY display_name"#
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .all(&sql_pool)
 | 
					            .all(&sql_pool)
 | 
				
			||||||
            .await
 | 
					            .await
 | 
				
			||||||
@ -154,10 +155,12 @@ mod tests {
 | 
				
			|||||||
            vec![
 | 
					            vec![
 | 
				
			||||||
                SimpleUser {
 | 
					                SimpleUser {
 | 
				
			||||||
                    display_name: None,
 | 
					                    display_name: None,
 | 
				
			||||||
 | 
					                    first_name: None,
 | 
				
			||||||
                    uuid: crate::uuid!("a02eaf13-48a7-30f6-a3d4-040ff7c52b04")
 | 
					                    uuid: crate::uuid!("a02eaf13-48a7-30f6-a3d4-040ff7c52b04")
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                SimpleUser {
 | 
					                SimpleUser {
 | 
				
			||||||
                    display_name: Some("John Doe".to_owned()),
 | 
					                    display_name: Some("John Doe".to_owned()),
 | 
				
			||||||
 | 
					                    first_name: Some("John".to_owned()),
 | 
				
			||||||
                    uuid: crate::uuid!("986765a5-3f03-389e-b47b-536b2d6e1bec")
 | 
					                    uuid: crate::uuid!("986765a5-3f03-389e-b47b-536b2d6e1bec")
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
				
			|||||||
@ -949,7 +949,7 @@ mod tests {
 | 
				
			|||||||
                    dn: "uid=bob,ou=people,dc=example,dc=com".to_string(),
 | 
					                    dn: "uid=bob,ou=people,dc=example,dc=com".to_string(),
 | 
				
			||||||
                    attributes: vec![LdapPartialAttribute {
 | 
					                    attributes: vec![LdapPartialAttribute {
 | 
				
			||||||
                        atype: "memberOf".to_string(),
 | 
					                        atype: "memberOf".to_string(),
 | 
				
			||||||
                        vals: vec![b"uid=rockstars,ou=groups,dc=example,dc=com".to_vec()]
 | 
					                        vals: vec![b"cn=rockstars,ou=groups,dc=example,dc=com".to_vec()]
 | 
				
			||||||
                    }],
 | 
					                    }],
 | 
				
			||||||
                }),
 | 
					                }),
 | 
				
			||||||
                make_search_success(),
 | 
					                make_search_success(),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								set-password/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								set-password/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "lldap_set_password"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					anyhow = "*"
 | 
				
			||||||
 | 
					rand = "0.8"
 | 
				
			||||||
 | 
					serde = "1"
 | 
				
			||||||
 | 
					serde_json = "1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.clap]
 | 
				
			||||||
 | 
					features = ["std", "color", "suggestions", "derive", "env"]
 | 
				
			||||||
 | 
					version = "4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.lldap_auth]
 | 
				
			||||||
 | 
					path = "../auth"
 | 
				
			||||||
 | 
					features = ["opaque_client"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.reqwest]
 | 
				
			||||||
 | 
					version = "*"
 | 
				
			||||||
 | 
					default-features = false
 | 
				
			||||||
 | 
					features = ["json", "blocking", "rustls-tls"]
 | 
				
			||||||
							
								
								
									
										133
									
								
								set-password/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								set-password/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
				
			|||||||
 | 
					use anyhow::{bail, ensure, Context, Result};
 | 
				
			||||||
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					use lldap_auth::{opaque, registration};
 | 
				
			||||||
 | 
					use serde::Serialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Set the password for a user in LLDAP.
 | 
				
			||||||
 | 
					#[derive(Debug, Parser, Clone)]
 | 
				
			||||||
 | 
					pub struct CliOpts {
 | 
				
			||||||
 | 
					    /// Base LLDAP url, e.g. "https://lldap/".
 | 
				
			||||||
 | 
					    #[clap(short, long)]
 | 
				
			||||||
 | 
					    pub base_url: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Admin username.
 | 
				
			||||||
 | 
					    #[clap(long, default_value = "admin")]
 | 
				
			||||||
 | 
					    pub admin_username: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Admin password.
 | 
				
			||||||
 | 
					    #[clap(long)]
 | 
				
			||||||
 | 
					    pub admin_password: Option<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Connection token (JWT).
 | 
				
			||||||
 | 
					    #[clap(short, long)]
 | 
				
			||||||
 | 
					    pub token: Option<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Username.
 | 
				
			||||||
 | 
					    #[clap(short, long)]
 | 
				
			||||||
 | 
					    pub username: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// New password for the user.
 | 
				
			||||||
 | 
					    #[clap(short, long)]
 | 
				
			||||||
 | 
					    pub password: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn get_token(base_url: &str, username: &str, password: &str) -> Result<String> {
 | 
				
			||||||
 | 
					    let client = reqwest::blocking::Client::new();
 | 
				
			||||||
 | 
					    let response = client
 | 
				
			||||||
 | 
					        .post(format!("{base_url}/auth/simple/login"))
 | 
				
			||||||
 | 
					        .header(reqwest::header::CONTENT_TYPE, "application/json")
 | 
				
			||||||
 | 
					        .body(
 | 
				
			||||||
 | 
					            serde_json::to_string(&lldap_auth::login::ClientSimpleLoginRequest {
 | 
				
			||||||
 | 
					                username: username.to_string(),
 | 
				
			||||||
 | 
					                password: password.to_string(),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .expect("Failed to encode the username/password as json to log in"),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .send()?
 | 
				
			||||||
 | 
					        .error_for_status()?;
 | 
				
			||||||
 | 
					    Ok(serde_json::from_str::<lldap_auth::login::ServerLoginResponse>(&response.text()?)?.token)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn call_server(url: &str, token: &str, body: impl Serialize) -> Result<String> {
 | 
				
			||||||
 | 
					    let client = reqwest::blocking::Client::new();
 | 
				
			||||||
 | 
					    let request = client
 | 
				
			||||||
 | 
					        .post(url)
 | 
				
			||||||
 | 
					        .header("Content-Type", "application/json")
 | 
				
			||||||
 | 
					        .bearer_auth(token)
 | 
				
			||||||
 | 
					        .body(serde_json::to_string(&body)?);
 | 
				
			||||||
 | 
					    let response = request.send()?.error_for_status()?;
 | 
				
			||||||
 | 
					    Ok(response.text()?)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn register_start(
 | 
				
			||||||
 | 
					    base_url: &str,
 | 
				
			||||||
 | 
					    token: &str,
 | 
				
			||||||
 | 
					    request: registration::ClientRegistrationStartRequest,
 | 
				
			||||||
 | 
					) -> Result<registration::ServerRegistrationStartResponse> {
 | 
				
			||||||
 | 
					    let request = Some(request);
 | 
				
			||||||
 | 
					    let data = call_server(
 | 
				
			||||||
 | 
					        &format!("{base_url}/auth/opaque/register/start"),
 | 
				
			||||||
 | 
					        token,
 | 
				
			||||||
 | 
					        request,
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					    serde_json::from_str(&data).context("Could not parse response")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn register_finish(
 | 
				
			||||||
 | 
					    base_url: &str,
 | 
				
			||||||
 | 
					    token: &str,
 | 
				
			||||||
 | 
					    request: registration::ClientRegistrationFinishRequest,
 | 
				
			||||||
 | 
					) -> Result<()> {
 | 
				
			||||||
 | 
					    let request = Some(request);
 | 
				
			||||||
 | 
					    call_server(
 | 
				
			||||||
 | 
					        &format!("{base_url}/auth/opaque/register/finish"),
 | 
				
			||||||
 | 
					        token,
 | 
				
			||||||
 | 
					        request,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .map(|_| ())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() -> Result<()> {
 | 
				
			||||||
 | 
					    let opts = CliOpts::parse();
 | 
				
			||||||
 | 
					    ensure!(
 | 
				
			||||||
 | 
					        opts.password.len() >= 8,
 | 
				
			||||||
 | 
					        "New password is too short, expected at least 8 characters"
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    ensure!(
 | 
				
			||||||
 | 
					        opts.base_url.starts_with("http://") || opts.base_url.starts_with("https://"),
 | 
				
			||||||
 | 
					        "Base URL should start with `http://` or `https://`"
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    let token = match (opts.token.as_ref(), opts.admin_password.as_ref()) {
 | 
				
			||||||
 | 
					        (Some(token), _) => token.clone(),
 | 
				
			||||||
 | 
					        (None, Some(password)) => {
 | 
				
			||||||
 | 
					            get_token(&opts.base_url, &opts.admin_username, password).context("While logging in")?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        (None, None) => bail!("Either the token or the admin password is required"),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut rng = rand::rngs::OsRng;
 | 
				
			||||||
 | 
					    let registration_start_request =
 | 
				
			||||||
 | 
					        opaque::client::registration::start_registration(&opts.password, &mut rng)
 | 
				
			||||||
 | 
					            .context("Could not initiate password change")?;
 | 
				
			||||||
 | 
					    let start_request = registration::ClientRegistrationStartRequest {
 | 
				
			||||||
 | 
					        username: opts.username.to_string(),
 | 
				
			||||||
 | 
					        registration_start_request: registration_start_request.message,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let res = register_start(&opts.base_url, &token, start_request)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let registration_finish = opaque::client::registration::finish_registration(
 | 
				
			||||||
 | 
					        registration_start_request.state,
 | 
				
			||||||
 | 
					        res.registration_response,
 | 
				
			||||||
 | 
					        &mut rng,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    .context("Error during password change")?;
 | 
				
			||||||
 | 
					    let req = registration::ClientRegistrationFinishRequest {
 | 
				
			||||||
 | 
					        server_data: res.server_data,
 | 
				
			||||||
 | 
					        registration_upload: registration_finish.message,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    register_finish(&opts.base_url, &token, req)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("Successfully changed {}'s password", &opts.username);
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user