Commit Diff


commit - b2c9f618aa4d760f0edfc7dbf6bcd01ca38aca17
commit + d36998aec867c8134466eccfe048dc8671eecca5
blob - c23b8863b3184121b8c368dd247b965685f04711
blob + 3dea3bfa8e197050bf539168af1366e3871504f4
--- gotd/gotd.conf.5
+++ gotd/gotd.conf.5
@@ -380,6 +380,10 @@ When several commits are batched in a single send oper
 the fields are available for each commit object.
 .It Dv repo
 The repository name as string.
+.It Dv auth_user
+The committer's user account as authenticated by
+.Xr gotd 8
+as a string.
 .It Dv id
 The commit ID as string, may be abbreviated.
 .It Dv committer
@@ -448,6 +452,10 @@ to be set:
 .Bl -tag -compact -width Ds
 .It Dv repo
 The repository name as string.
+.It Dv auth_user
+The committer's user account as authenticated by
+.Xr gotd 8
+as a string.
 .It Dv ref
 The removed branch reference.
 .It Dv id
@@ -458,6 +466,10 @@ The tag notification has the following fields, all gua
 .Bl -tag -width Ds
 .It repo
 The repository name as string.
+.It Dv auth_user
+The committer's user account as authenticated by
+.Xr gotd 8
+as a string.
 .It tag
 The tag reference.
 .It tagger
blob - c4375525ccc474f8fe090e2653580512c0faf220
blob + 02ec51dafe5e458386554dc03f1fad6aa05c0026
--- gotd/gotd.h
+++ gotd/gotd.h
@@ -477,6 +477,8 @@ struct gotd_imsg_notification_content {
 struct gotd_imsg_notify {
 	char repo_name[NAME_MAX];
 	char subject_line[64];
+	size_t username_len;
+	/* Followed by username_len data bytes. */
 };
 
 int parse_config(const char *, enum gotd_procid, struct gotd *);
blob - 4ee2c0b6e836e4cf92abff873a5b9c94c9da2a21
blob + 110aa3179a27bd4af209fd577262ccccdd94f82b
--- gotd/libexec/got-notify-http/got-notify-http.c
+++ gotd/libexec/got-notify-http/got-notify-http.c
@@ -46,7 +46,7 @@ static int		 http_timeout = 300;	/* 5 minutes in secon
 __dead static void
 usage(void)
 {
-	fprintf(stderr, "usage: %s [-c] -r repo -h host -p port path\n",
+	fprintf(stderr, "usage: %s [-c] -r repo -h host -p port -u user path\n",
 	    getprogname());
 	exit(1);
 }
@@ -200,7 +200,7 @@ json_author(FILE *fp, const char *type, char *address,
 }
 
 static int
-jsonify_branch_rm(FILE *fp, char *line, const char *repo)
+jsonify_branch_rm(FILE *fp, char *line, const char *repo, const char *user)
 {
 	char	*ref, *id;
 
@@ -220,6 +220,8 @@ jsonify_branch_rm(FILE *fp, char *line, const char *re
 	fputc('{', fp);
 	json_field(fp, "type", "branch-deleted", 1);
 	json_field(fp, "repo", repo, 1);
+	if (user)
+		json_field(fp, "auth_user", user, 1);
 	json_field(fp, "ref", ref, 1);
 	json_field(fp, "id", id, 0);
 	fputc('}', fp);
@@ -228,7 +230,7 @@ jsonify_branch_rm(FILE *fp, char *line, const char *re
 }
 
 static int
-jsonify_commit_short(FILE *fp, char *line, const char *repo)
+jsonify_commit_short(FILE *fp, char *line, const char *repo, const char *user)
 {
 	char	*t, *date, *id, *author, *message;
 
@@ -252,6 +254,8 @@ jsonify_commit_short(FILE *fp, char *line, const char 
 
 	fprintf(fp, "{\"type\":\"commit\",\"short\":true,");
 	json_field(fp, "repo", repo, 1);
+	if (user)
+		json_field(fp, "auth_user", user, 1);
 	json_field(fp, "id", id, 1);
 	json_author(fp, "committer", author, 1);
 	json_date(fp, "date", date, 1);
@@ -262,7 +266,8 @@ jsonify_commit_short(FILE *fp, char *line, const char 
 }
 
 static int
-jsonify_commit(FILE *fp, const char *repo, char **line, ssize_t *linesize)
+jsonify_commit(FILE *fp, const char *repo, const char *user,
+    char **line, ssize_t *linesize)
 {
 	const char	*errstr;
 	char		*author = NULL;
@@ -291,6 +296,8 @@ jsonify_commit(FILE *fp, const char *repo, char **line
 
 	fprintf(fp, "{\"type\":\"commit\",\"short\":false,");
 	json_field(fp, "repo", repo, 1);
+	if (user)
+		json_field(fp, "auth_user", user, 1);
 	json_field(fp, "id", l, 1);
 
 	while (!done) {
@@ -557,7 +564,8 @@ jsonify_commit(FILE *fp, const char *repo, char **line
 }
 
 static int
-jsonify_tag(FILE *fp, const char *repo, char **line, ssize_t *linesize)
+jsonify_tag(FILE *fp, const char *repo, const char *user,
+    char **line, ssize_t *linesize)
 {
 	const char	*errstr;
 	char		*l;
@@ -580,6 +588,8 @@ jsonify_tag(FILE *fp, const char *repo, char **line, s
 	fputc('{', fp);
 	json_field(fp, "type", "tag", 1);
 	json_field(fp, "repo", repo, 1);
+	if (user)
+		json_field(fp, "auth_user", user, 1);
 	json_field(fp, "tag", l, 1);
 
 	while (!done) {
@@ -688,7 +698,7 @@ jsonify_tag(FILE *fp, const char *repo, char **line, s
 }
 
 static int
-jsonify(FILE *fp, const char *repo)
+jsonify(FILE *fp, const char *repo, const char *user)
 {
 	char		*line = NULL;
 	size_t		 linesize = 0;
@@ -708,25 +718,26 @@ jsonify(FILE *fp, const char *repo)
 		needcomma = 1;
 
 		if (strncmp(line, "Removed refs/heads/", 19) == 0) {
-			if (jsonify_branch_rm(fp, line, repo) == -1)
+			if (jsonify_branch_rm(fp, line, repo, user) == -1)
 				fatal("jsonify_branch_rm");
 			continue;
 		}
 
 		if (strncmp(line, "commit ", 7) == 0) {
-			if (jsonify_commit(fp, repo, &line, &linesize) == -1)
+			if (jsonify_commit(fp, repo, user,
+			    &line, &linesize) == -1)
 				fatal("jsonify_commit");
 			continue;
 		}
 
 		if (*line >= '0' && *line <= '9') {
-			if (jsonify_commit_short(fp, line, repo) == -1)
+			if (jsonify_commit_short(fp, line, repo, user) == -1)
 				fatal("jsonify_commit_short");
 			continue;
 		}
 
 		if (strncmp(line, "tag ", 4) == 0) {
-			if (jsonify_tag(fp, repo, &line, &linesize) == -1)
+			if (jsonify_tag(fp, repo, user, &line, &linesize) == -1)
 				fatal("jsonify_tag");
 			continue;
 		}
@@ -843,6 +854,7 @@ main(int argc, char **argv)
 	const char	*errstr;
 	const char	*repo = NULL;
 	const char	*host = NULL, *port = NULL, *path = NULL;
+	const char	*gotd_auth_user = NULL;
 	char		*auth, *line, *spc;
 	size_t		 len;
 	ssize_t		 r;
@@ -858,7 +870,7 @@ main(int argc, char **argv)
 
 	log_init(0, LOG_DAEMON);
 
-	while ((ch = getopt(argc, argv, "ch:p:r:")) != -1) {
+	while ((ch = getopt(argc, argv, "ch:p:r:u:")) != -1) {
 		switch (ch) {
 		case 'c':
 			tls = 1;
@@ -872,6 +884,9 @@ main(int argc, char **argv)
 		case 'r':
 			repo = optarg;
 			break;
+		case 'u':
+			gotd_auth_user = optarg;
+			break;
 		default:
 			usage();
 		}
@@ -909,7 +924,7 @@ main(int argc, char **argv)
 	if (tmpfp == NULL)
 		fatal("opentemp");
 
-	jsonify(tmpfp, repo);
+	jsonify(tmpfp, repo, gotd_auth_user);
 
 	paylen = ftello(tmpfp);
 	if (paylen == -1)
blob - cc0b17db44d592bb3d0b20f73b44556cac260e9c
blob + 936d588b3f5a49ce4f818a58d0f599adf5ddc0b9
--- gotd/notify.c
+++ gotd/notify.c
@@ -261,9 +261,10 @@ notify_email(struct gotd_notification_target *target, 
 }
 
 static void
-notify_http(struct gotd_notification_target *target, const char *repo, int fd)
+notify_http(struct gotd_notification_target *target, const char *repo,
+    const char *username, int fd)
 {
-	const char *argv[10];
+	const char *argv[12];
 	int argc = 0;
 
 	argv[argc++] = GOTD_PATH_PROG_NOTIFY_HTTP;
@@ -276,6 +277,8 @@ notify_http(struct gotd_notification_target *target, c
 	argv[argc++] = target->conf.http.hostname;
 	argv[argc++] = "-p";
 	argv[argc++] = target->conf.http.port;
+	argv[argc++] = "-u";
+	argv[argc++] = username;
 
 	argv[argc++] = target->conf.http.path;
 
@@ -294,12 +297,15 @@ send_notification(struct imsg *imsg, struct gotd_imsge
 	struct gotd_repo *repo;
 	struct gotd_notification_target *target;
 	int fd;
+	char *username = NULL;
 
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
-	if (datalen != sizeof(inotify))
+	if (datalen < sizeof(inotify))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
 
-	memcpy(&inotify, imsg->data, datalen);
+	memcpy(&inotify, imsg->data, sizeof(inotify));
+	if (datalen != sizeof(inotify) + inotify.username_len)
+		return got_error(GOT_ERR_PRIVSEP_LEN);
 
 	repo = gotd_find_repo_by_name(inotify.repo_name, gotd_notify.repos);
 	if (repo == NULL)
@@ -309,18 +315,23 @@ send_notification(struct imsg *imsg, struct gotd_imsge
 	if (fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
+	username = strndup(imsg->data + sizeof(inotify), inotify.username_len);
+	if (username == NULL)
+		return got_error_from_errno("strndup");
+
 	if (lseek(fd, 0, SEEK_SET) == -1) {
 		err = got_error_from_errno("lseek");
 		goto done;
 	}
 
+
 	STAILQ_FOREACH(target, &repo->notification_targets, entry) {
 		switch (target->type) {
 		case GOTD_NOTIFICATION_VIA_EMAIL:
 			notify_email(target, inotify.subject_line, fd);
 			break;
 		case GOTD_NOTIFICATION_VIA_HTTP:
-			notify_http(target, repo->name, fd);
+			notify_http(target, repo->name, username, fd);
 			break;
 		}
 	}
@@ -332,6 +343,7 @@ send_notification(struct imsg *imsg, struct gotd_imsge
 	}
 done:
 	close(fd);
+	free(username);
 	return err;
 }
 
blob - 1d073e97037a9cb64129ca446a58b0f3fe2a2a62
blob + d957c78baa66812aad479f8135c63971e8397e2e
--- gotd/session_write.c
+++ gotd/session_write.c
@@ -497,6 +497,7 @@ forward_notification(struct gotd_session_client *clien
 	size_t datalen;
 	struct gotd_imsg_notify inotify;
 	const char *action;
+	struct ibuf *wbuf;
 
 	memset(&inotify, 0, sizeof(inotify));
 
@@ -566,13 +567,28 @@ forward_notification(struct gotd_session_client *clien
 	    "%s: %s %s %s", gotd_session.repo_cfg->name,
 	    client->username, action, notif->refname);
 
-	if (gotd_imsg_compose_event(iev, GOTD_IMSG_NOTIFY,
-	    PROC_SESSION_WRITE, notif->fd, &inotify, sizeof(inotify))
-	    == -1) {
-		err = got_error_from_errno("imsg compose NOTIFY");
+	inotify.username_len = strlen(client->username);
+	wbuf = imsg_create(&iev->ibuf, GOTD_IMSG_NOTIFY,
+	    PROC_SESSION_WRITE, gotd_session.pid,
+	    sizeof(inotify) + inotify.username_len);
+	if (wbuf == NULL) {
+		err = got_error_from_errno("imsg_create NOTIFY");
+		goto done;
+	}
+	if (imsg_add(wbuf, &inotify, sizeof(inotify)) == -1) {
+		err = got_error_from_errno("imsg_add NOTIFY");
 		goto done;
 	}
+	if (imsg_add(wbuf, client->username, inotify.username_len) == -1) {
+		err = got_error_from_errno("imsg_add NOTIFY");
+		goto done;
+	}
+
+	ibuf_fd_set(wbuf, notif->fd);
 	notif->fd = -1;
+
+	imsg_close(&iev->ibuf, wbuf);
+	gotd_imsg_event_add(iev);
 done:
 	if (notif->fd != -1)
 		close(notif->fd);
blob - 23a8d91f145b36a4fca7522f147af43bd6c98956
blob + 33fbf586ff94a94ca7f4a10f06a3814106db946d
--- regress/gotd/http_notification.sh
+++ regress/gotd/http_notification.sh
@@ -64,6 +64,7 @@ test_file_changed() {
 		"type":"commit",
 		"short":false,
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"id":"$commit_id",
 		"author":{
 			"full":"$GOT_AUTHOR",
@@ -155,6 +156,7 @@ test_bad_utf8() {
 		"type":"commit",
 		"short":false,
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"id":"$commit_id",
 		"author":{
 			"full":"$GOT_AUTHOR",
@@ -255,6 +257,7 @@ test_many_commits_not_summarized() {
 			"type":"commit",
 			"short":false,
 			"repo":"test-repo",
+			"auth_user":"${GOTD_DEVUSER}",
 			"id":"$commit_id",
 			"author":{
 				"full":"$GOT_AUTHOR",
@@ -359,6 +362,7 @@ test_many_commits_summarized() {
 			"type":"commit",
 			"short":true,
 			"repo":"test-repo",
+			"auth_user":"${GOTD_DEVUSER}",
 			"id":"$commit_id",
 			"committer":{
 				"user":"$GOT_AUTHOR_8"
@@ -439,6 +443,7 @@ test_branch_created() {
 		"type":"commit",
 		"short":false,
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"id":"$commit_id",
 		"author":{
 			"full":"$GOT_AUTHOR",
@@ -517,6 +522,7 @@ test_branch_removed() {
 	{"notifications":[{
 		"type":"branch-deleted",
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"ref":"refs/heads/newbranch",
 		"id":"$commit_id"
 	}]}
@@ -570,6 +576,7 @@ test_tag_created() {
 	{"notifications":[{
 		"type":"tag",
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"tag":"refs/tags/1.0",
 		"tagger":{
 			"full":"$GOT_AUTHOR",
@@ -649,6 +656,7 @@ test_tag_changed() {
 	{"notifications":[{
 		"type":"tag",
 		"repo":"test-repo",
+		"auth_user":"${GOTD_DEVUSER}",
 		"tag":"refs/tags/1.0",
 		"tagger":{
 			"full":"$GOT_AUTHOR",