IndieAuth support (#1811)
* Able to authenticate user against IndieAuth. For #1273 * WIP server indieauth endpoint. For https://github.com/owncast/owncast/issues/1272 * Add migration to remove access tokens from user * Add authenticated bool to user for display purposes * Add indieauth modal and auth flair to display names. For #1273 * Validate URLs and display errors * Renames, cleanups * Handle relative auth endpoint paths. Add error handling for missing redirects. * Disallow using display names in use by registered users. Closes #1810 * Verify code verifier via code challenge on callback * Use relative path to authorization_endpoint * Post-rebase fixes * Use a timestamp instead of a bool for authenticated * Propertly handle and display error in modal * Use auth'ed timestamp to derive authenticated flag to display in chat * don't redirect unless a URL is present avoids redirecting to `undefined` if there was an error * improve error message if owncast server URL isn't set * fix IndieAuth PKCE implementation use SHA256 instead of SHA1, generates a longer code verifier (must be 43-128 chars long), fixes URL-safe SHA256 encoding * return real profile data for IndieAuth response * check the code verifier in the IndieAuth server * Linting * Add new chat settings modal anad split up indieauth ui * Remove logging error * Update the IndieAuth modal UI. For #1273 * Add IndieAuth repsonse error checking * Disable IndieAuth client if server URL is not set. * Add explicit error messages for specific error types * Fix bad logic * Return OAuth-keyed error responses for indieauth server * Display IndieAuth error in plain text with link to return to main page * Remove redundant check * Add additional detail to error * Hide IndieAuth details behind disclosure details * Break out migration into two steps because some people have been runing dev in production * Add auth option to user dropdown Co-authored-by: Aaron Parecki <aaron@parecki.com>
This commit is contained in:
@@ -104,16 +104,17 @@ func makeUserMessageEventFromRowData(row rowData) events.UserMessageEvent {
|
||||
scopeSlice := strings.Split(scopes, ",")
|
||||
|
||||
u := user.User{
|
||||
ID: *row.userID,
|
||||
AccessToken: "",
|
||||
DisplayName: displayName,
|
||||
DisplayColor: displayColor,
|
||||
CreatedAt: createdAt,
|
||||
DisabledAt: row.userDisabledAt,
|
||||
NameChangedAt: row.userNameChangedAt,
|
||||
PreviousNames: previousUsernames,
|
||||
Scopes: scopeSlice,
|
||||
IsBot: isBot,
|
||||
ID: *row.userID,
|
||||
DisplayName: displayName,
|
||||
DisplayColor: displayColor,
|
||||
CreatedAt: createdAt,
|
||||
DisabledAt: row.userDisabledAt,
|
||||
NameChangedAt: row.userNameChangedAt,
|
||||
PreviousNames: previousUsernames,
|
||||
AuthenticatedAt: row.userAuthenticatedAt,
|
||||
Authenticated: row.userAuthenticatedAt != nil,
|
||||
Scopes: scopeSlice,
|
||||
IsBot: isBot,
|
||||
}
|
||||
|
||||
message := events.UserMessageEvent{
|
||||
@@ -195,14 +196,15 @@ type rowData struct {
|
||||
image *string
|
||||
link *string
|
||||
|
||||
userDisplayName *string
|
||||
userDisplayColor *int
|
||||
userCreatedAt *time.Time
|
||||
userDisabledAt *time.Time
|
||||
previousUsernames *string
|
||||
userNameChangedAt *time.Time
|
||||
userScopes *string
|
||||
userType *string
|
||||
userDisplayName *string
|
||||
userDisplayColor *int
|
||||
userCreatedAt *time.Time
|
||||
userDisabledAt *time.Time
|
||||
previousUsernames *string
|
||||
userNameChangedAt *time.Time
|
||||
userAuthenticatedAt *time.Time
|
||||
userScopes *string
|
||||
userType *string
|
||||
}
|
||||
|
||||
func getChat(query string) []interface{} {
|
||||
@@ -235,9 +237,11 @@ func getChat(query string) []interface{} {
|
||||
&row.userDisabledAt,
|
||||
&row.previousUsernames,
|
||||
&row.userNameChangedAt,
|
||||
&row.userAuthenticatedAt,
|
||||
&row.userScopes,
|
||||
&row.userType,
|
||||
); err != nil {
|
||||
log.Errorln(err)
|
||||
log.Errorln("There is a problem converting query to chat objects. Please report this:", query)
|
||||
break
|
||||
}
|
||||
@@ -274,7 +278,7 @@ func GetChatModerationHistory() []interface{} {
|
||||
}
|
||||
|
||||
// Get all messages regardless of visibility
|
||||
query := "SELECT messages.id, user_id, body, title, subtitle, image, link, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at, scopes, users.type FROM messages INNER JOIN users ON messages.user_id = users.id ORDER BY timestamp DESC"
|
||||
query := "SELECT messages.id, user_id, body, title, subtitle, image, link, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at, authenticated_at, scopes, type FROM messages INNER JOIN users ON messages.user_id = users.id ORDER BY timestamp DESC"
|
||||
result := getChat(query)
|
||||
|
||||
_historyCache = &result
|
||||
@@ -285,7 +289,7 @@ func GetChatModerationHistory() []interface{} {
|
||||
// GetChatHistory will return all the chat messages suitable for returning as user-facing chat history.
|
||||
func GetChatHistory() []interface{} {
|
||||
// Get all visible messages
|
||||
query := fmt.Sprintf("SELECT messages.id,messages.user_id, messages.body, messages.title, messages.subtitle, messages.image, messages.link, messages.eventType, messages.hidden_at, messages.timestamp, users.display_name, users.display_color, users.created_at, users.disabled_at, users.previous_names, users.namechanged_at, users.scopes, users.type FROM messages LEFT JOIN users ON messages.user_id = users.id WHERE hidden_at IS NULL AND disabled_at IS NULL ORDER BY timestamp DESC LIMIT %d", maxBacklogNumber)
|
||||
query := fmt.Sprintf("SELECT messages.id,messages.user_id, messages.body, messages.title, messages.subtitle, messages.image, messages.link, messages.eventType, messages.hidden_at, messages.timestamp, users.display_name, users.display_color, users.created_at, users.disabled_at, users.previous_names, users.namechanged_at, users.authenticated_at, users.scopes, users.type FROM messages LEFT JOIN users ON messages.user_id = users.id WHERE hidden_at IS NULL AND disabled_at IS NULL ORDER BY timestamp DESC LIMIT %d", maxBacklogNumber)
|
||||
m := getChat(query)
|
||||
|
||||
// Invert order of messages
|
||||
@@ -305,7 +309,7 @@ func SetMessageVisibilityForUserID(userID string, visible bool) error {
|
||||
|
||||
// Get a list of IDs to send to the connected clients to hide
|
||||
ids := make([]string, 0)
|
||||
query := fmt.Sprintf("SELECT messages.id, user_id, body, title, subtitle, image, link, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at, scopes, type FROM messages INNER JOIN users ON messages.user_id = users.id WHERE user_id IS '%s'", userID)
|
||||
query := fmt.Sprintf("SELECT messages.id, user_id, body, title, subtitle, image, link, eventType, hidden_at, timestamp, display_name, display_color, created_at, disabled_at, previous_names, namechanged_at, authenticated, scopes, type FROM messages INNER JOIN users ON messages.user_id = users.id WHERE user_id IS '%s'", userID)
|
||||
messages := getChat(query)
|
||||
|
||||
if len(messages) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user