Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix login bugs, enable support for saving user's credentials, and add "Change User" and "Remember Me?" options #1374

Merged
merged 10 commits into from
Sep 21, 2023
9 changes: 6 additions & 3 deletions components/data/SceneManager.brs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import "pkg:/source/roku_modules/log/LogMixin.brs"
import "pkg:/source/utils/config.brs"
import "pkg:/source/utils/session.bs"

sub init()
m.log = log.Logger("SceneManager")
Expand Down Expand Up @@ -77,16 +79,17 @@ end sub
sub popScene()
group = m.groups.pop()
if group <> invalid
if group.isSubType("JFGroup")
groupType = group.subtype()
if groupType = "JFGroup"
unregisterOverhangData(group)
else if group.isSubType("JFVideo")
else if groupType = "JFVideo"
' Stop video to make sure app communicates stop playstate to server
group.control = "stop"
end if

group.visible = false

if group.isSubType("JFScreen")
if groupType = "JFScreen"
group.callFunc("OnScreenHidden")
end if
else
Expand Down
7 changes: 3 additions & 4 deletions components/data/UserData.brs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ sub loadFromRegistry(id as string)
end sub

sub saveToRegistry()
set_user_setting("username", m.top.username)
set_user_setting("token", m.top.token)

users = parseJson(get_setting("available_users", "[]"))
this_user = invalid
for each user in users
Expand Down Expand Up @@ -57,7 +54,9 @@ function setPreference(key as string, value as string)
end function

sub setActive()
set_setting("active_user", m.top.id)
if m.global.session.user.settings["global.rememberme"]
set_setting("active_user", m.top.id)
end if
end sub

sub setServer(hostname as string)
Expand Down
33 changes: 30 additions & 3 deletions components/settings/settings.brs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "pkg:/source/utils/config.brs"
import "pkg:/source/utils/misc.brs"
import "pkg:/source/roku_modules/log/LogMixin.brs"
import "pkg:/source/api/sdk.bs"

sub init()
m.log = log.Logger("Settings")
Expand Down Expand Up @@ -160,14 +161,40 @@ end sub


sub boolSettingChanged()

if m.boolSetting.focusedChild = invalid then return
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]

if m.boolSetting.checkedItem
set_user_setting(selectedSetting.settingName, "true")
session.user.settings.Save(selectedSetting.settingName, "true")
if Left(selectedSetting.settingName, 7) = "global."
' global user setting
' save to main registry block
set_setting(selectedSetting.settingName, "true")
' setting specific triggers
if selectedSetting.settingName = "global.rememberme"
print "m.global.session.user.id=", m.global.session.user.id
set_setting("active_user", m.global.session.user.id)
end if
else
' regular user setting
' save to user specific registry block
set_user_setting(selectedSetting.settingName, "true")
end if
else
set_user_setting(selectedSetting.settingName, "false")
session.user.settings.Save(selectedSetting.settingName, "false")
if Left(selectedSetting.settingName, 7) = "global."
' global user setting
' save to main registry block
set_setting(selectedSetting.settingName, "false")
' setting specific triggers
if selectedSetting.settingName = "global.rememberme"
unset_setting("active_user")
end if
else
' regular user setting
' save to user specific registry block
set_user_setting(selectedSetting.settingName, "false")
end if
end if
end sub

Expand Down
20 changes: 20 additions & 0 deletions locale/en_US/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1208,5 +1208,25 @@
<translation>Disable the HEVC codec on this device. This may improve playback for some devices (ultra).</translation>
<extracomment>User Setting - Setting description</extracomment>
</message>
<message>
<source>Global</source>
<translation>Global</translation>
<extracomment>User Setting - Setting title</extracomment>
</message>
<message>
<source>Global settings that affect everyone that uses this Roku device.</source>
<translation>Global settings that affect everyone that uses this Roku device.</translation>
<extracomment>User Setting - Setting description</extracomment>
</message>
<message>
<source>Remember Me?</source>
<translation>Remember Me?</translation>
<extracomment>User Setting - Setting title</extracomment>
</message>
<message>
<source>Remember the currently logged in user and try to log them in again next time you start the Jellyfin app.</source>
<translation>Remember the currently logged in user and try to log them in again next time you start the Jellyfin app.</translation>
<extracomment>User Setting - Setting description</extracomment>
</message>
</context>
</TS>
14 changes: 14 additions & 0 deletions settings/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
[
{
"title": "Global",
"description": "Global settings that affect everyone that uses this Roku device.",
"children": [
{
"title": "Remember Me?",
"description": "Remember the currently logged in user and try to log them in again next time you start the Jellyfin app.",
"settingName": "global.rememberme",
"type": "bool",
"default": "false"
}

]
},
{
"title": "Playback",
"description": "Settings relating to playback and supported codec and media types.",
Expand Down
4 changes: 4 additions & 0 deletions source/Main.brs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ sub Main (args as dynamic) as void
SignOut(false)
sceneManager.callFunc("clearScenes")
goto app_start
else if button.id = "change_user"
SignOut(false)
sceneManager.callFunc("clearScenes")
goto app_start
else if button.id = "sign_out"
SignOut()
sceneManager.callFunc("clearScenes")
Expand Down
115 changes: 79 additions & 36 deletions source/ShowScenes.brs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function LoginFlow(startOver = false as boolean)
function LoginFlow()
'Collect Jellyfin server and user information
start_login:

Expand Down Expand Up @@ -41,9 +41,11 @@ function LoginFlow(startOver = false as boolean)
activeUser = get_setting("active_user")
if activeUser = invalid
print "No active user found in registry"
user_select:
SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting
publicUsers = GetPublicUsers()
if publicUsers.count()
numPubUsers = publicUsers.count()
if numPubUsers > 0
publicUsersNodes = []
for each item in publicUsers
user = CreateObject("roSGNode", "PublicUserData")
Expand All @@ -55,18 +57,70 @@ function LoginFlow(startOver = false as boolean)
publicUsersNodes.push(user)
end for
userSelected = CreateUserSelectGroup(publicUsersNodes)

SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
if userSelected = "backPressed"
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
return LoginFlow(true)
session.server.Delete()
unset_setting("server")
goto start_login
else
print "A public user was selected with username=" + userSelected
' save userid to session
for each user in publicUsersNodes
if user.name = userSelected
session.user.Update("id", user.id)
exit for
end if
end for
' try to login with token from registry
myToken = get_user_setting("token")
if myToken <> invalid
' check if token is valid
print "Auth token found in registry for selected user"
session.user.Update("authToken", myToken)
print "Attempting to use API with auth token"
currentUser = AboutMe()
if currentUser = invalid
print "Auth token is no longer valid - deleting token"
unset_user_setting("token")
else
print "Success! Auth token is still valid"
session.user.Login(currentUser)
LoadUserPreferences()
LoadUserAbilities()
return true
end if
else
print "No auth token found in registry for selected user"
end if
' try to login with password from registry
userData = invalid
myPassword = get_user_setting("password")
if isValid(myPassword)
' saved password found for selected user
print "Saved credentials found for selected user. Attempting to login"
userData = get_token(userSelected, myPassword)
if isValid(userData)
print "login success!"
session.user.Login(userData)
LoadUserPreferences()
LoadUserAbilities()
return true
end if
else
print "No saved credentials found for selected user"
end if
'Try to login without password. If the token is valid, we're done
print "Attempting to login with no password"
userData = get_token(userSelected, "")
if isValid(userData)
print "login success!"
session.user.Login(userData)
LoadUserPreferences()
LoadUserAbilities()
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
return true
else
print "Auth failed. Password required"
end if
end if
else
Expand All @@ -75,8 +129,13 @@ function LoginFlow(startOver = false as boolean)
passwordEntry = CreateSigninGroup(userSelected)
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
if passwordEntry = "backPressed"
m.global.sceneManager.callFunc("clearScenes")
return LoginFlow(true)
if numPubUsers > 0
goto user_select
else
session.server.Delete()
unset_setting("server")
goto start_login
end if
end if
else
print "Active user found in registry"
Expand All @@ -89,19 +148,19 @@ function LoginFlow(startOver = false as boolean)
print "Attempting to use API with auth token"
currentUser = AboutMe()
if currentUser = invalid
print "Auth token is no longer valid - restart login flow"
print "Auth token is no longer valid - delete token and restart login flow"
unset_user_setting("token")
unset_setting("active_user")
session.user.Logout()
goto start_login
else
print "Success! Auth token is still valid"
session.user.Login(currentUser)
end if
else
print "No auth token found in registry"
myUsername = get_setting("username")
myPassword = get_setting("password")

print "Checking to see if we have saved credentials"
myUsername = get_user_setting("username")
myPassword = get_user_setting("password")
userData = invalid

if isValid(myUsername) and isValid(myPassword)
Expand All @@ -110,8 +169,8 @@ function LoginFlow(startOver = false as boolean)
userData = get_token(myUsername, myPassword)
else
print "Username in registry is an empty string"
unset_setting("username")
unset_setting("password")
unset_user_setting("username")
unset_user_setting("password")
end if
else if isValid(myUsername) and not isValid(myPassword)
print "Username found in registry but no password"
Expand All @@ -120,7 +179,7 @@ function LoginFlow(startOver = false as boolean)
userData = get_token(myUsername, "")
else
print "Username in registry is an empty string"
unset_setting("username")
unset_user_setting("username")
end if

else if not isValid(myUsername) and not isValid(myPassword)
Expand Down Expand Up @@ -362,25 +421,6 @@ function CreateSigninGroup(user = "")

group.findNode("prompt").text = tr("Sign In")

'Load in any saved server data and see if we can just log them in...
server = m.global.session.server.url
if isValid(server)
server = LCase(server)'Saved server data is always lowercase
end if
saved = get_setting("saved_servers")
if isValid(saved)
savedServers = ParseJson(saved)
for each item in savedServers.serverList
if item.baseUrl = server and isValid(item.username) and isValid(item.password)
userData = get_token(item.username, item.password)
if isValid(userData)
session.user.Login(userData)
return "true"
end if
end if
end for
end if

config = group.findNode("configOptions")
username_field = CreateObject("roSGNode", "ConfigData")
username_field.label = tr("Username")
Expand Down Expand Up @@ -447,9 +487,11 @@ function CreateSigninGroup(user = "")
activeUser = get_token(username.value, password.value)
if isValid(activeUser)
session.user.Login(activeUser)
set_setting("username", username.value)
set_setting("password", password.value)
' save credentials
if checkbox.checkedState[0] = true
set_user_setting("username", username.value)
set_user_setting("password", password.value)
cewert marked this conversation as resolved.
Show resolved Hide resolved
set_user_setting("token", activeUser.token)
'Update our saved server list, so next time the user can just click and go
UpdateSavedServerList()
end if
Expand Down Expand Up @@ -515,6 +557,7 @@ function CreateHomeGroup()
new_options = []
options_buttons = [
{ "title": "Search", "id": "goto_search" },
{ "title": "Change user", "id": "change_user" },
{ "title": "Change server", "id": "change_server" },
{ "title": "Sign out", "id": "sign_out" }
]
Expand Down
24 changes: 3 additions & 21 deletions source/api/userauth.brs
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,10 @@ function AboutMe(id = "" as string)
end function

sub SignOut(deleteSavedEntry = true as boolean)
if m.global.session.user.id <> invalid
if m.global.session.user.id <> invalid and deleteSavedEntry = true
unset_user_setting("token")
unset_setting("username")
unset_setting("password")
if deleteSavedEntry = true
'Also delete any credentials in the "saved servers" list
saved = get_setting("saved_servers")
server = m.global.session.server.url
if server <> invalid
server = LCase(server)
savedServers = ParseJson(saved)
newServers = { serverList: [] }
for each item in savedServers.serverList
if item.baseUrl = server
item.username = ""
item.password = ""
end if
newServers.serverList.Push(item)
end for
set_setting("saved_servers", FormatJson(newServers))
end if
end if
unset_user_setting("username")
unset_user_setting("password")
end if
unset_setting("active_user")
session.user.Logout()
Expand Down
Loading