message telling a user their own rights have changed.
/** @brief Callbacks for server state monitoring */
const disorder_eclient_log_callbacks log_callbacks = {
- log_connected,
- log_completed,
- log_failed,
- log_moved,
- log_playing,
- log_queue,
- log_recent_added,
- log_recent_removed,
- log_removed,
- log_scratched,
- log_state,
- log_volume,
- log_rescanned
+ .connected = log_connected,
+ .completed = log_completed,
+ .failed = log_failed,
+ .moved = log_moved,
+ .playing = log_playing,
+ .queue = log_queue,
+ .recent_added = log_recent_added,
+ .recent_removed = log_recent_removed,
+ .removed = log_removed,
+ .scratched = log_scratched,
+ .state = log_state,
+ .volume = log_volume,
+ .rescanned = log_rescanned
};
/** @brief Update everything */
To simplify client implementation, \fBstate\fR commands reflecting the current
state are sent at the start of the log.
.RE
+.TB
+.B user-add \fIUSERNAME\fR
+A user was created.
+.TP
+.B user-delete \fIUSERNAME\fR
+A user was deleted.
+.TP
+.B user-edit \fIUSERNAME\fR \fIPROPERTY\fR
+Some property of a user was edited.
+.TP
+.B user-confirm \fIUSERNAME\fR
+A user's login was confirmed (via the web interface).
.TP
.B volume \fILEFT\fR \fIRIGHT\fR
The volume changed.
is as defined in
.B "TRACK INFORMATION"
above.
+.PP
+The \fBuser-*\fR messages are only sent to admin users, and are not sent over
+non-local connections unless \fBremote_userman\fR is enabled.
.SH "CHARACTER ENCODING"
All data sent by both server and client is encoded using UTF-8.
Moreover it must be valid UTF-8, i.e. non-minimal sequences are not
static void logentry_state(disorder_eclient *c, int nvec, char **vec);
static void logentry_volume(disorder_eclient *c, int nvec, char **vec);
static void logentry_rescanned(disorder_eclient *c, int nvec, char **vec);
+static void logentry_user_add(disorder_eclient *c, int nvec, char **vec);
+static void logentry_user_confirm(disorder_eclient *c, int nvec, char **vec);
+static void logentry_user_delete(disorder_eclient *c, int nvec, char **vec);
+static void logentry_user_edit(disorder_eclient *c, int nvec, char **vec);
/* Tables ********************************************************************/
LE(rescanned, 0, 0),
LE(scratched, 2, 2),
LE(state, 1, 1),
+ LE(user_add, 1, 1),
+ LE(user_confirm, 1, 1),
+ LE(user_delete, 1, 1),
+ LE(user_edit, 2, 2),
LE(volume, 2, 2)
};
c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
+static void logentry_user_add(disorder_eclient *c,
+ int attribute((unused)) nvec, char **vec) {
+ if(c->log_callbacks->user_add)
+ c->log_callbacks->user_add(c->log_v, vec[0]);
+}
+
+static void logentry_user_confirm(disorder_eclient *c,
+ int attribute((unused)) nvec, char **vec) {
+ if(c->log_callbacks->user_confirm)
+ c->log_callbacks->user_confirm(c->log_v, vec[0]);
+}
+
+static void logentry_user_delete(disorder_eclient *c,
+ int attribute((unused)) nvec, char **vec) {
+ if(c->log_callbacks->user_delete)
+ c->log_callbacks->user_delete(c->log_v, vec[0]);
+}
+
+static void logentry_user_edit(disorder_eclient *c,
+ int attribute((unused)) nvec, char **vec) {
+ if(c->log_callbacks->user_edit)
+ c->log_callbacks->user_edit(c->log_v, vec[0], vec[1]);
+}
+
static const struct {
unsigned long bit;
const char *enable;
typedef struct disorder_eclient_log_callbacks {
/** @brief Called on (re-)connection */
void (*connected)(void *v);
-
+
+ /** @brief Called when @p track finished playing successfully */
void (*completed)(void *v, const char *track);
+
+ /** @brief Called when @p track fails for some reason */
void (*failed)(void *v, const char *track, const char *status);
+
+ /** @brief Called when @p user moves some track or tracks in the queue
+ *
+ * Fetch the queue again to find out what the new order is - the
+ * rearrangement could in principle be arbitrarily complicated.
+ */
void (*moved)(void *v, const char *user);
+
+ /** @brief Called when @p track starts playing
+ *
+ * @p user might be 0.
+ */
void (*playing)(void *v, const char *track, const char *user/*maybe 0*/);
+
+ /** @brief Called when @p q is added to the queue
+ *
+ * Fetch the queue again to find out where the in the queue it was added.
+ */
void (*queue)(void *v, struct queue_entry *q);
+
+ /** @brief Called when @p q is added to the recent list */
void (*recent_added)(void *v, struct queue_entry *q);
+
+ /** @brief Called when @p id is removed from the recent list */
void (*recent_removed)(void *v, const char *id);
+
+ /** @brief Called when @id is removed from the queue
+ *
+ * @p user might be 0.
+ */
void (*removed)(void *v, const char *id, const char *user/*maybe 0*/);
+
+ /** @brief Called when @p track is scratched */
void (*scratched)(void *v, const char *track, const char *user);
+
+ /** @brief Called with the current state whenever it changes
+ *
+ * State bits are:
+ * - @ref DISORDER_PLAYING_ENABLED
+ * - @ref DISORDER_RANDOM_ENABLED
+ * - @ref DISORDER_TRACK_PAUSED
+ * - @ref DISORDER_PLAYING
+ * - @ref DISORDER_CONNECTED
+ */
void (*state)(void *v, unsigned long state);
+
+ /** @brief Called when the volume changes */
void (*volume)(void *v, int left, int right);
+
+ /** @brief Called when a rescan completes */
void (*rescanned)(void *v);
+
+ /** @brief Called when a user is created (admins only) */
+ void (*user_add)(void *v, const char *user);
+
+ /** @brief Called when a user is confirmed (admins only) */
+ void (*user_confirm)(void *v, const char *user);
+
+ /** @brief Called when a user is deleted (admins only) */
+ void (*user_delete)(void *v, const char *user);
+
+ /** @brief Called when a user is edited (admins only) */
+ void (*user_edit)(void *v, const char *user, const char *property);
} disorder_eclient_log_callbacks;
/* State bits */
user, rights, email);
else
info("created user '%s' with rights '%s'", user, rights);
+ eventlog("user-add", user, (char *)0);
return 0;
}
}
return -1;
}
info("deleted user '%s'", user);
+ eventlog("user-delete", user, (char *)0);
return 0;
}
if(e) {
error(0, "unknown user '%s'", user);
return -1;
- } else
+ } else {
+ eventlog("user-edit", user, key, (char *)0);
return 0;
+ }
}
/** @brief List all users
switch(e) {
case 0:
info("registration confirmed for user '%s'", user);
+ eventlog("user-confirm", user, (char *)0);
return 0;
case DB_NOTFOUND:
error(0, "confirmation for nonexistent user '%s'", user);
eventlog_remove(c->lo);
return;
}
+ /* user-* messages are restricted */
+ if(!strncmp(msg, "user-", 5)) {
+ /* They are only sent to admin users */
+ if(!(c->rights & RIGHT_ADMIN))
+ return;
+ /* They are not sent over TCP connections unless remote user-management is
+ * enabled */
+ if(!config->remote_userman && !(c->rights & RIGHT__LOCAL))
+ return;
+ }
sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" %s\n",
(uintmax_t)time(0), msg);
}