297 lines
7.5 KiB
Bash
Executable File
297 lines
7.5 KiB
Bash
Executable File
#! /bin/bash
|
|
|
|
# TODO: replace with ~/database
|
|
db="$HOME/webhooks"
|
|
|
|
# Make sure we don't fallback to a simple "*.foo" when no files matched the glob pattern
|
|
shopt -s nullglob
|
|
|
|
# These are the functions used by commands, search for ENTRYPOINT to see where the script starts!
|
|
|
|
from_url() {
|
|
# Return hex representation of URL
|
|
echo -n "$@" | base64
|
|
}
|
|
|
|
from_hex() {
|
|
# Return string representation (URL) of hex
|
|
echo -n "$@" | base64 -d
|
|
}
|
|
|
|
# When we reach those commands, $user is necessarily set
|
|
|
|
help_cmd() {
|
|
echo "TODO provide some help here :D"
|
|
}
|
|
|
|
list_cmd() {
|
|
# If we receive a repo argument, we print the subscribers to it
|
|
if [ $# -gt 0 ]; then
|
|
r="$1"
|
|
rhex="$(from_url "$r")"
|
|
if [ ! -f $db/."$rhex".secret ]; then
|
|
echo "ERROR: Repository $r not found"
|
|
exit 1
|
|
fi
|
|
for u in "$db"/"$rhex".*; do
|
|
# For each subscriber, print the username
|
|
u="$(basename "$u")"
|
|
u="${u#$rhex.}"
|
|
echo "$u"
|
|
done
|
|
exit 0
|
|
fi
|
|
for f in "$db"/*."$user"; do
|
|
rhex="$(basename "$f" ".$user")"
|
|
r="$(from_hex "$rhex")"
|
|
output="$r"
|
|
owner="$(cat "$db/.$rhex.owner")"
|
|
if [[ "$owner" = "$user" ]]; then
|
|
secret="$(cat "$db/.$rhex.secret")"
|
|
output="$output\t$secret"
|
|
fi
|
|
# Need -e to interpret the \t
|
|
echo -e "$output"
|
|
done
|
|
# New iteration for unsubscribed tasks you still own
|
|
for f in $db/owned-by/$user/*; do
|
|
rhex="$(basename "$f")"
|
|
owner="$(cat "$db/.$rhex.owner")"
|
|
if [[ "$owner" != "$user" ]]; then
|
|
echo "FATAL ERROR: HOW CAN THIS HAPPEN?"
|
|
echo "$rhex claims owner is $owner, but $user claims it as well."
|
|
exit 1
|
|
fi
|
|
if [ -f "$db/$rhex.$user" ]; then
|
|
# user is subscribed so it's already printed
|
|
continue
|
|
fi
|
|
r="$(from_hex "$rhex")"
|
|
secret="$(cat "$db/.$rhex.secret")"
|
|
output="$rhex\t$secret\tx"
|
|
# Still need -e for tabulations
|
|
echo -e "$output"
|
|
done
|
|
}
|
|
|
|
add_cmd() {
|
|
if [ $# -lt 1 ]; then
|
|
echo "ERROR: You need to provide a repo to add!"
|
|
fi
|
|
r="$1"
|
|
rhex="$(from_url "$1")"
|
|
# Check if the repository is already registered
|
|
if [ -f "$db/.$rhex.owner" ]; then
|
|
# If it is, we try to subscribe instead
|
|
echo "[forgehook] This repository is already registered, subscribing to it."
|
|
subscribe_cmd "$r"
|
|
exit $?
|
|
fi
|
|
# Ensure we can clone the repo
|
|
tmp="$(mktemp -d)"
|
|
if ! git clone "$r" "$tmp/repo"; then
|
|
rm -r "$tmp"
|
|
echo "ERROR: The repository cannot be cloned: $r"
|
|
exit 1
|
|
fi
|
|
|
|
# Need to force for .git files
|
|
rm -rf "$tmp"
|
|
echo "$user" > $db/."$rhex".owner
|
|
if [ ! -d $db/owned-by/"$user" ]; then
|
|
if ! mkdir $db/owned-by/"$user"; then
|
|
echo "FATAL ERROR: Cannot create $db/owned-by/$user. WTF?"
|
|
exit 1
|
|
fi
|
|
fi
|
|
touch $db/owned-by/"$user"/"$rhex"
|
|
if [ -z ${2+NULL} ]; then
|
|
secret="$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c32)"
|
|
else
|
|
secret="$2"
|
|
fi
|
|
echo "$secret" > $db/."$rhex".secret
|
|
echo "[forgehook] Your secret for $r is now:"
|
|
echo "$secret"
|
|
subscribe_cmd "$r"
|
|
}
|
|
|
|
remove_cmd() {
|
|
FORCE=0
|
|
if [ $# -lt 1 ]; then
|
|
echo "ERROR: You need to provide a repo to remove!"
|
|
elif [ $# -gt 1 ]; then
|
|
if [[ "$2" = "force" ]] || [[ "$2" = "-f" ]] || [[ "$2" = "--force" ]]; then
|
|
FORCE=1
|
|
else
|
|
echo "ERROR: Unrecognized argument $2"
|
|
fi
|
|
fi
|
|
|
|
# If the command is not forced, unsubscribe instead
|
|
if [[ $FORCE = 0 ]]; then
|
|
unsubscribe_cmd "$1"
|
|
exit $?
|
|
fi
|
|
# We want to remove it for real, for all users
|
|
r="$1"
|
|
rhex="$(from_url "$1")"
|
|
# Check the repo is registered with us
|
|
if [ ! -f "$db/.$rhex.owner" ]; then
|
|
echo "ERROR: This repo isn't registered $r"
|
|
exit 1
|
|
fi
|
|
owner="$(cat $db/."$rhex".owner)"
|
|
if [[ "$owner" != "$user" ]]; then
|
|
echo "ERROR: Repository $r is claimed by $owner, you cannot remove it."
|
|
exit 1
|
|
fi
|
|
rm $db/owned-by/"$user"/"$rhex"
|
|
rm $db/."$rhex".owner
|
|
rm $db/."$rhex".secret
|
|
# Do not fail if there are no more subscriptions
|
|
rm -f $db/"$rhex".*
|
|
echo "[forgehook] Successfully removed $r"
|
|
}
|
|
|
|
subscribe_cmd() {
|
|
if [ $# -lt 1 ]; then
|
|
echo "ERROR: You need to provide a repository URL to subscribe to"
|
|
exit 0
|
|
fi
|
|
|
|
r="$1"
|
|
rhex="$(from_url $r)"
|
|
|
|
if [ ! -f $db/."$rhex".owner ]; then
|
|
echo "ERROR: Repository $r hasn't been added yet, maybe try:"
|
|
echo "forgehook add \"$r\""
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f $db/"$rhex"."$user" ]; then
|
|
echo "[forgehook] You are already subscribed to $r"
|
|
exit 0
|
|
fi
|
|
|
|
touch $db/"$rhex"."$user"
|
|
owner="$(cat $db/."$rhex".owner)"
|
|
echo "[forgehook] Subscribed to $r (owner: $owner)"
|
|
}
|
|
|
|
unsubscribe_cmd() {
|
|
if [ $# -lt 1 ]; then
|
|
echo "ERROR: You need to provide a repository URL to subscribe to"
|
|
exit 1
|
|
fi
|
|
|
|
r="$1"
|
|
rhex="$(from_url "$r")"
|
|
|
|
if [ ! -f $db/."$rhex".owner ]; then
|
|
echo "ERROR: Repository $r hasn't been added yet, cannot unsubscribe. Run forgehook without argument to list your repositories"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f $db/"$rhex"."$user" ]; then
|
|
echo "ERROR: You are not subscribed to repository $r"
|
|
exit 1
|
|
fi
|
|
|
|
rm $db/"$rhex"."$user"
|
|
echo "[forgehook] Successfully unsubscribed from $r"
|
|
}
|
|
|
|
secret_cmd() {
|
|
if [ $# -lt 1 ]; then
|
|
echo "ERROR: You need to provide a repository URL to view/change its secret"
|
|
exit 1
|
|
fi
|
|
|
|
r="$1"
|
|
rhex="$(from_url "$r")"
|
|
|
|
if [ ! -f $db/."$rhex".owner ]; then
|
|
echo "ERROR: Repository $r hasn't been added yet. Run forgehook without argument to list your repositories"
|
|
exit 1
|
|
fi
|
|
|
|
owner="$(cat $db/."$rhex".owner)"
|
|
db_owner="$(find /usr/local/bin/forgehook-db -maxdepth 0 -printf '%u')"
|
|
if [[ "$owner" != "$user" ]] && [[ "$(id -gn $SUDO_GID)" != "$db_owner" ]]; then
|
|
# TODO: when running with group forgehook, we don't exit because it's an endpoint asking (done?)
|
|
echo "ERROR: Repository $r is owned by $owner"
|
|
exit 1
|
|
fi
|
|
|
|
if [ $# -gt 1 ]; then
|
|
secret="$2"
|
|
echo "$secret" > "$db/.$rhex.secret"
|
|
echo "[forgehook] Your secret for $r is now:"
|
|
echo "$secret"
|
|
exit 0
|
|
fi
|
|
|
|
cat $db/."$rhex".secret
|
|
}
|
|
|
|
# ENTRYPOINT
|
|
|
|
# We trust sudo security!
|
|
user="$SUDO_USER"
|
|
|
|
# If no argument is supplied, we do the list
|
|
if [[ $# = 0 ]]; then
|
|
list_cmd
|
|
exit $?
|
|
fi
|
|
|
|
# Ensure directoies are correctly setup
|
|
if [ ! -d $db ]; then
|
|
if ! mkdir $db; then
|
|
echo "$(id -run)"
|
|
echo "FATAL ERROR: Cannot create $db"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ ! -d $db/owned-by/"$user" ]; then
|
|
# -p in case owned-by/ doesn't exist yet
|
|
if ! mkdir -p $db/owned-by/"$user"; then
|
|
echo "FATAL ERROR: Cannot create $db/owned-by/$user"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
command="$1"
|
|
# Remove first argument from arguments
|
|
shift
|
|
|
|
case $command in
|
|
"help"|"-f"|"--help")
|
|
help_cmd
|
|
;;
|
|
"list")
|
|
list_cmd $@
|
|
;;
|
|
"add")
|
|
add_cmd $@
|
|
;;
|
|
"remove"|"rm")
|
|
remove_cmd $@
|
|
;;
|
|
"subscribe"|"sub")
|
|
subscribe_cmd $@
|
|
;;
|
|
"unsubscribe"|"unsub")
|
|
unsubcribe_cmd $@
|
|
;;
|
|
"secret")
|
|
secret_cmd $@
|
|
;;
|
|
*)
|
|
echo "ERROR: Command not found: $command"
|
|
help_cmd
|
|
exit 1
|
|
esac
|