mirror of
https://github.com/Mic92/nixos-wiki-infra.git
synced 2025-06-26 04:32:18 +02:00
add wiki-user-search tool
This commit is contained in:
parent
f48e28fd44
commit
ecdbd13bc8
24
README.md
24
README.md
@ -36,6 +36,30 @@ $ ls -la /tmp/restore/var/lib/mediawiki-uploads/
|
||||
$ umount /tmp/restore/
|
||||
```
|
||||
|
||||
## Searching for wiki users (wiki admins only)
|
||||
|
||||
The `wiki-user-search` tool allows administrators to search for MediaWiki users
|
||||
by username, email, or real name. Since it connects to PostgreSQL, it must be
|
||||
run as the `postgres` user:
|
||||
|
||||
```bash
|
||||
# Search by username
|
||||
$ sudo -u postgres wiki-user-search "admin"
|
||||
|
||||
# Search by email domain
|
||||
$ sudo -u postgres wiki-user-search "@example.com"
|
||||
|
||||
# Search by real name
|
||||
$ sudo -u postgres wiki-user-search "John Smith"
|
||||
|
||||
# Limit results (default is 10)
|
||||
$ sudo -u postgres wiki-user-search "test" -l 20
|
||||
```
|
||||
|
||||
The tool displays results in a table format showing Username, Email, and Real
|
||||
Name. It uses fuzzy matching with case-insensitive search and prioritizes exact
|
||||
matches over partial matches.
|
||||
|
||||
## Applying terraform
|
||||
|
||||
Updating hetzner ssh keys:
|
||||
|
@ -46,6 +46,7 @@
|
||||
...
|
||||
}:
|
||||
{
|
||||
packages = import ./pkgs { inherit pkgs; };
|
||||
|
||||
checks =
|
||||
let
|
||||
|
@ -50,6 +50,10 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
environment.systemPackages = [
|
||||
(pkgs.python3.pkgs.callPackage ../../pkgs/wiki-user-search { })
|
||||
];
|
||||
|
||||
services.mediawiki = {
|
||||
name = "NixOS Wiki";
|
||||
enable = true;
|
||||
|
5
pkgs/default.nix
Normal file
5
pkgs/default.nix
Normal file
@ -0,0 +1,5 @@
|
||||
{ pkgs }:
|
||||
|
||||
{
|
||||
wiki-user-search = pkgs.python3.pkgs.callPackage ./wiki-user-search { };
|
||||
}
|
32
pkgs/wiki-user-search/default.nix
Normal file
32
pkgs/wiki-user-search/default.nix
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
lib,
|
||||
psycopg2,
|
||||
buildPythonApplication,
|
||||
}:
|
||||
|
||||
buildPythonApplication {
|
||||
pname = "wiki-user-search";
|
||||
version = "1.0.0";
|
||||
|
||||
src = ./.;
|
||||
|
||||
format = "other";
|
||||
|
||||
propagatedBuildInputs = [ psycopg2 ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
install -Dm755 wiki-user-search.py $out/bin/wiki-user-search
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "MediaWiki user search tool with fuzzy matching";
|
||||
homepage = "https://github.com/NixOS/nixos-wiki-infra";
|
||||
license = licenses.mit;
|
||||
maintainers = [ ];
|
||||
mainProgram = "wiki-user-search";
|
||||
};
|
||||
}
|
132
pkgs/wiki-user-search/wiki-user-search.py
Normal file
132
pkgs/wiki-user-search/wiki-user-search.py
Normal file
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
MediaWiki User Search Tool
|
||||
Fuzzy search for users by username, real name, or email
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import psycopg2
|
||||
import sys
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
def search_users(search_term: str, limit: int = 10) -> List[Tuple[str, str, str]]:
|
||||
"""
|
||||
Search for users using fuzzy matching on username, real name, or email.
|
||||
Returns list of (username, email, real_name) tuples.
|
||||
"""
|
||||
# Connect via Unix socket
|
||||
try:
|
||||
conn = psycopg2.connect(
|
||||
host="/run/postgresql", dbname="mediawiki", user="postgres"
|
||||
)
|
||||
except psycopg2.Error as e:
|
||||
print(f"Error connecting to database: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
cur = conn.cursor()
|
||||
|
||||
# Use PostgreSQL's ILIKE for case-insensitive pattern matching
|
||||
query = """
|
||||
SELECT DISTINCT
|
||||
user_name,
|
||||
user_email,
|
||||
user_real_name,
|
||||
CASE
|
||||
WHEN LOWER(user_name) = LOWER(%s) THEN 1
|
||||
WHEN LOWER(user_email) = LOWER(%s) THEN 1
|
||||
WHEN LOWER(user_real_name) = LOWER(%s) THEN 1
|
||||
WHEN LOWER(user_name) LIKE LOWER(%s) THEN 2
|
||||
WHEN LOWER(user_email) LIKE LOWER(%s) THEN 2
|
||||
WHEN LOWER(user_real_name) LIKE LOWER(%s) THEN 2
|
||||
ELSE 3
|
||||
END as match_score
|
||||
FROM mediawiki."user"
|
||||
WHERE
|
||||
user_name ILIKE %s
|
||||
OR user_email ILIKE %s
|
||||
OR user_real_name ILIKE %s
|
||||
ORDER BY match_score, user_name
|
||||
LIMIT %s
|
||||
"""
|
||||
|
||||
# Create search pattern with wildcards
|
||||
search_pattern = f"%{search_term}%"
|
||||
|
||||
# Execute query with all parameters
|
||||
cur.execute(
|
||||
query,
|
||||
(
|
||||
search_term,
|
||||
search_term,
|
||||
search_term, # Exact match checks
|
||||
search_pattern,
|
||||
search_pattern,
|
||||
search_pattern, # Pattern match checks
|
||||
search_pattern,
|
||||
search_pattern,
|
||||
search_pattern, # WHERE clause
|
||||
limit,
|
||||
),
|
||||
)
|
||||
|
||||
results = []
|
||||
for row in cur.fetchall():
|
||||
username, email, real_name, _ = row
|
||||
results.append((username or "", email or "", real_name or ""))
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
return results
|
||||
|
||||
|
||||
def print_table(results: List[Tuple[str, str, str]]) -> None:
|
||||
"""Print search results as a formatted table."""
|
||||
if not results:
|
||||
print("No users found matching the search term.")
|
||||
return
|
||||
|
||||
# Calculate column widths
|
||||
username_width = max(len("Username"), max(len(r[0]) for r in results))
|
||||
email_width = max(len("Email"), max(len(r[1]) for r in results))
|
||||
real_name_width = max(len("Real Name"), max(len(r[2]) for r in results))
|
||||
|
||||
# Print header
|
||||
print(
|
||||
f"{'Username':<{username_width}} | {'Email':<{email_width}} | {'Real Name':<{real_name_width}}"
|
||||
)
|
||||
print(f"{'-' * username_width}-+-{'-' * email_width}-+-{'-' * real_name_width}")
|
||||
|
||||
# Print rows
|
||||
for username, email, real_name in results:
|
||||
print(
|
||||
f"{username:<{username_width}} | {email:<{email_width}} | {real_name:<{real_name_width}}"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Search MediaWiki users by username, email, or real name"
|
||||
)
|
||||
parser.add_argument(
|
||||
"search_term", help="Search term to match against username, email, or real name"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--limit",
|
||||
"-l",
|
||||
type=int,
|
||||
default=10,
|
||||
help="Maximum number of results (default: 10)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Search for users
|
||||
results = search_users(args.search_term, args.limit)
|
||||
|
||||
# Print results as table
|
||||
print_table(results)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user