HaikuDepot: Restore logged in user across sessions.
* Store the username in the app settings. The password was already stored in the keyring. Restore the username upon next launch. * Display the logged in user in the main window. * Added "Log out" menu entry. * When the password could not be retrieved from the keyring (also because the user rejects the keyring dialog), unset the username. * Allow unsetting the username by passing an empty name.
This commit is contained in:
@@ -30,14 +30,19 @@
|
|||||||
static const char* kHaikuDepotKeyring = "HaikuDepot";
|
static const char* kHaikuDepotKeyring = "HaikuDepot";
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageFilters
|
|
||||||
|
|
||||||
|
|
||||||
PackageFilter::~PackageFilter()
|
PackageFilter::~PackageFilter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModelListener::~ModelListener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageFilters
|
||||||
|
|
||||||
|
|
||||||
class AnyFilter : public PackageFilter {
|
class AnyFilter : public PackageFilter {
|
||||||
public:
|
public:
|
||||||
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
||||||
@@ -368,6 +373,13 @@ Model::~Model()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Model::AddListener(const ModelListenerRef& listener)
|
||||||
|
{
|
||||||
|
return fListeners.Add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PackageList
|
PackageList
|
||||||
Model::CreatePackageList() const
|
Model::CreatePackageList() const
|
||||||
{
|
{
|
||||||
@@ -661,14 +673,27 @@ Model::StopPopulatingAllPackages()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Model::SetUser(const BString& username)
|
Model::SetUsername(BString username)
|
||||||
{
|
{
|
||||||
BPasswordKey key;
|
BString password;
|
||||||
BKeyStore keyStore;
|
if (username.Length() > 0) {
|
||||||
if (keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD, username,
|
BPasswordKey key;
|
||||||
key) == B_OK) {
|
BKeyStore keyStore;
|
||||||
SetAuthorization(username, key.Password(), false);
|
if (keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD, username,
|
||||||
|
key) == B_OK) {
|
||||||
|
password = key.Password();
|
||||||
|
} else {
|
||||||
|
username = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
SetAuthorization(username, password, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BString&
|
||||||
|
Model::Username() const
|
||||||
|
{
|
||||||
|
return fWebAppInterface.Username();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -676,7 +701,7 @@ void
|
|||||||
Model::SetAuthorization(const BString& username, const BString& password,
|
Model::SetAuthorization(const BString& username, const BString& password,
|
||||||
bool storePassword)
|
bool storePassword)
|
||||||
{
|
{
|
||||||
if (storePassword) {
|
if (storePassword && username.Length() > 0 && password.Length() > 0) {
|
||||||
BPasswordKey key(password, B_KEY_PURPOSE_WEB, username);
|
BPasswordKey key(password, B_KEY_PURPOSE_WEB, username);
|
||||||
BKeyStore keyStore;
|
BKeyStore keyStore;
|
||||||
keyStore.AddKeyring(kHaikuDepotKeyring);
|
keyStore.AddKeyring(kHaikuDepotKeyring);
|
||||||
@@ -685,6 +710,8 @@ Model::SetAuthorization(const BString& username, const BString& password,
|
|||||||
|
|
||||||
BAutolock locker(&fLock);
|
BAutolock locker(&fLock);
|
||||||
fWebAppInterface.SetAuthorization(username, password);
|
fWebAppInterface.SetAuthorization(username, password);
|
||||||
|
|
||||||
|
_NotifyAuthorizationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1146,3 +1173,18 @@ Model::_HasNativeIcon(const BMessage& message) const
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - listener notification methods
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Model::_NotifyAuthorizationChanged()
|
||||||
|
{
|
||||||
|
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||||
|
const ModelListenerRef& listener = fListeners.ItemAtFast(i);
|
||||||
|
if (listener.Get() != NULL)
|
||||||
|
listener->AuthorizationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,17 @@ public:
|
|||||||
typedef BReference<PackageFilter> PackageFilterRef;
|
typedef BReference<PackageFilter> PackageFilterRef;
|
||||||
|
|
||||||
|
|
||||||
|
class ModelListener : public BReferenceable {
|
||||||
|
public:
|
||||||
|
virtual ~ModelListener();
|
||||||
|
|
||||||
|
virtual void AuthorizationChanged() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BReference<ModelListener> ModelListenerRef;
|
||||||
|
typedef List<ModelListenerRef, false> ModelListenerList;
|
||||||
|
|
||||||
|
|
||||||
class Model {
|
class Model {
|
||||||
public:
|
public:
|
||||||
Model();
|
Model();
|
||||||
@@ -33,6 +44,8 @@ public:
|
|||||||
BLocker* Lock()
|
BLocker* Lock()
|
||||||
{ return &fLock; }
|
{ return &fLock; }
|
||||||
|
|
||||||
|
bool AddListener(const ModelListenerRef& listener);
|
||||||
|
|
||||||
// !Returns new PackageInfoList from current parameters
|
// !Returns new PackageInfoList from current parameters
|
||||||
PackageList CreatePackageList() const;
|
PackageList CreatePackageList() const;
|
||||||
|
|
||||||
@@ -110,7 +123,8 @@ public:
|
|||||||
const BString& PreferredLanguage() const
|
const BString& PreferredLanguage() const
|
||||||
{ return fPreferredLanguage; }
|
{ return fPreferredLanguage; }
|
||||||
|
|
||||||
void SetUser(const BString& username);
|
void SetUsername(BString username);
|
||||||
|
const BString& Username() const;
|
||||||
void SetAuthorization(const BString& username,
|
void SetAuthorization(const BString& username,
|
||||||
const BString& password,
|
const BString& password,
|
||||||
bool storePassword);
|
bool storePassword);
|
||||||
@@ -139,6 +153,8 @@ private:
|
|||||||
int32 scaledWidth,
|
int32 scaledWidth,
|
||||||
bool fromCacheOnly);
|
bool fromCacheOnly);
|
||||||
|
|
||||||
|
void _NotifyAuthorizationChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLocker fLock;
|
BLocker fLock;
|
||||||
|
|
||||||
@@ -182,6 +198,8 @@ private:
|
|||||||
BString fPreferredLanguage;
|
BString fPreferredLanguage;
|
||||||
|
|
||||||
WebAppInterface fWebAppInterface;
|
WebAppInterface fWebAppInterface;
|
||||||
|
|
||||||
|
ModelListenerList fListeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ public:
|
|||||||
|
|
||||||
void SetAuthorization(const BString& username,
|
void SetAuthorization(const BString& username,
|
||||||
const BString& password);
|
const BString& password);
|
||||||
|
const BString& Username() const
|
||||||
|
{ return fUsername; }
|
||||||
|
|
||||||
void SetPreferredLanguage(const BString& language);
|
void SetPreferredLanguage(const BString& language);
|
||||||
void SetArchitecture(const BString& architecture);
|
void SetArchitecture(const BString& architecture);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
#include <PopUpMenu.h>
|
#include <PopUpMenu.h>
|
||||||
|
#include <StringView.h>
|
||||||
#include <TextControl.h>
|
#include <TextControl.h>
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
@@ -37,16 +38,23 @@ add_categories_to_menu(const CategoryList& categories, BMenu* menu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_small_font(BView* view)
|
||||||
|
{
|
||||||
|
BFont font;
|
||||||
|
view->GetFont(&font);
|
||||||
|
font.SetSize(ceilf(font.Size() * 0.8));
|
||||||
|
view->SetFont(&font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static BCheckBox*
|
static BCheckBox*
|
||||||
create_check_box(const char* label, const char* name)
|
create_check_box(const char* label, const char* name)
|
||||||
{
|
{
|
||||||
BMessage* message = new BMessage(MSG_FILTER_SELECTED);
|
BMessage* message = new BMessage(MSG_FILTER_SELECTED);
|
||||||
message->AddString("name", name);
|
message->AddString("name", name);
|
||||||
BCheckBox* checkBox = new BCheckBox(label, message);
|
BCheckBox* checkBox = new BCheckBox(label, message);
|
||||||
BFont font;
|
set_small_font(checkBox);
|
||||||
checkBox->GetFont(&font);
|
|
||||||
font.SetSize(ceilf(font.Size() * 0.75));
|
|
||||||
checkBox->SetFont(&font);
|
|
||||||
return checkBox;
|
return checkBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +98,11 @@ FilterView::FilterView()
|
|||||||
fSourceCodeCheckBox = create_check_box(
|
fSourceCodeCheckBox = create_check_box(
|
||||||
B_TRANSLATE("Source code"), "source code");
|
B_TRANSLATE("Source code"), "source code");
|
||||||
|
|
||||||
|
// Logged in user label
|
||||||
|
fUsername = new BStringView("logged in user", "");
|
||||||
|
set_small_font(fUsername);
|
||||||
|
fUsername->SetHighColor(80, 80, 80);
|
||||||
|
|
||||||
// Build layout
|
// Build layout
|
||||||
BLayoutBuilder::Group<>(this)
|
BLayoutBuilder::Group<>(this)
|
||||||
.AddGroup(B_HORIZONTAL)
|
.AddGroup(B_HORIZONTAL)
|
||||||
@@ -107,6 +120,7 @@ FilterView::FilterView()
|
|||||||
.Add(fDevelopmentCheckBox)
|
.Add(fDevelopmentCheckBox)
|
||||||
.Add(fSourceCodeCheckBox)
|
.Add(fSourceCodeCheckBox)
|
||||||
.AddGlue(0.5f)
|
.AddGlue(0.5f)
|
||||||
|
.Add(fUsername)
|
||||||
.End()
|
.End()
|
||||||
|
|
||||||
.SetInsets(B_USE_DEFAULT_SPACING)
|
.SetInsets(B_USE_DEFAULT_SPACING)
|
||||||
@@ -200,3 +214,17 @@ FilterView::AdoptCheckmarks(const Model& model)
|
|||||||
fSourceCodeCheckBox->SetValue(model.ShowSourcePackages());
|
fSourceCodeCheckBox->SetValue(model.ShowSourcePackages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FilterView::SetUsername(const BString& username)
|
||||||
|
{
|
||||||
|
BString label;
|
||||||
|
if (username.Length() == 0) {
|
||||||
|
label = B_TRANSLATE("Not logged in");
|
||||||
|
} else {
|
||||||
|
label = B_TRANSLATE("Logged in as %User%");
|
||||||
|
label.ReplaceAll("%User%", username);
|
||||||
|
}
|
||||||
|
fUsername->SetText(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
class BCheckBox;
|
class BCheckBox;
|
||||||
class BMenuField;
|
class BMenuField;
|
||||||
|
class BStringView;
|
||||||
class BTextControl;
|
class BTextControl;
|
||||||
class Model;
|
class Model;
|
||||||
|
|
||||||
@@ -30,8 +31,10 @@ public:
|
|||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
virtual void AdoptModel(const Model& model);
|
void AdoptModel(const Model& model);
|
||||||
virtual void AdoptCheckmarks(const Model& model);
|
void AdoptCheckmarks(const Model& model);
|
||||||
|
|
||||||
|
void SetUsername(const BString& username);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMenuField* fShowField;
|
BMenuField* fShowField;
|
||||||
@@ -42,6 +45,8 @@ private:
|
|||||||
BCheckBox* fInstalledCheckBox;
|
BCheckBox* fInstalledCheckBox;
|
||||||
BCheckBox* fDevelopmentCheckBox;
|
BCheckBox* fDevelopmentCheckBox;
|
||||||
BCheckBox* fSourceCodeCheckBox;
|
BCheckBox* fSourceCodeCheckBox;
|
||||||
|
|
||||||
|
BStringView* fUsername;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILTER_VIEW_H
|
#endif // FILTER_VIEW_H
|
||||||
|
|||||||
@@ -53,12 +53,14 @@
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MSG_MODEL_WORKER_DONE = 'mmwd',
|
MSG_MODEL_WORKER_DONE = 'mmwd',
|
||||||
MSG_REFRESH_DEPOTS = 'mrdp',
|
MSG_REFRESH_DEPOTS = 'mrdp',
|
||||||
MSG_LOG_IN = 'lgin',
|
MSG_LOG_IN = 'lgin',
|
||||||
MSG_PACKAGE_STATE_CHANGED = 'mpsc',
|
MSG_LOG_OUT = 'lgot',
|
||||||
MSG_SHOW_SOURCE_PACKAGES = 'ssrc',
|
MSG_AUTHORIZATION_CHANGED = 'athc',
|
||||||
MSG_SHOW_DEVELOP_PACKAGES = 'sdvl'
|
MSG_PACKAGE_STATE_CHANGED = 'mpsc',
|
||||||
|
MSG_SHOW_SOURCE_PACKAGES = 'ssrc',
|
||||||
|
MSG_SHOW_DEVELOP_PACKAGES = 'sdvl'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -83,11 +85,31 @@ struct RefreshWorkerParameters {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MessageModelListener : public ModelListener {
|
||||||
|
public:
|
||||||
|
MessageModelListener(const BMessenger& messenger)
|
||||||
|
:
|
||||||
|
fMessenger(messenger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AuthorizationChanged()
|
||||||
|
{
|
||||||
|
if (fMessenger.IsValid())
|
||||||
|
fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessenger fMessenger;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
||||||
:
|
:
|
||||||
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
|
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
|
||||||
B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||||
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
|
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
|
||||||
|
fModelListener(new MessageModelListener(BMessenger(this)), true),
|
||||||
fTerminating(false),
|
fTerminating(false),
|
||||||
fModelWorker(B_BAD_THREAD_ID)
|
fModelWorker(B_BAD_THREAD_ID)
|
||||||
{
|
{
|
||||||
@@ -117,6 +139,8 @@ MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
|||||||
fSplitView->SetCollapsible(0, false);
|
fSplitView->SetCollapsible(0, false);
|
||||||
fSplitView->SetCollapsible(1, false);
|
fSplitView->SetCollapsible(1, false);
|
||||||
|
|
||||||
|
fModel.AddListener(fModelListener);
|
||||||
|
|
||||||
// Restore settings
|
// Restore settings
|
||||||
BMessage columnSettings;
|
BMessage columnSettings;
|
||||||
if (settings.FindMessage("column settings", &columnSettings) == B_OK)
|
if (settings.FindMessage("column settings", &columnSettings) == B_OK)
|
||||||
@@ -128,6 +152,13 @@ MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
|||||||
if (settings.FindBool("show source packages", &showOption) == B_OK)
|
if (settings.FindBool("show source packages", &showOption) == B_OK)
|
||||||
fModel.SetShowSourcePackages(showOption);
|
fModel.SetShowSourcePackages(showOption);
|
||||||
|
|
||||||
|
BString username;
|
||||||
|
if (settings.FindString("username", &username) == B_OK
|
||||||
|
&& username.Length() > 0) {
|
||||||
|
fModel.SetUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start worker threads
|
||||||
BPackageRoster().StartWatching(this,
|
BPackageRoster().StartWatching(this,
|
||||||
B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
|
B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
|
||||||
|
|
||||||
@@ -212,6 +243,14 @@ MainWindow::MessageReceived(BMessage* message)
|
|||||||
_OpenLoginWindow();
|
_OpenLoginWindow();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MSG_LOG_OUT:
|
||||||
|
fModel.SetUsername("");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSG_AUTHORIZATION_CHANGED:
|
||||||
|
_UpdateAuthorization();
|
||||||
|
break;
|
||||||
|
|
||||||
case MSG_SHOW_SOURCE_PACKAGES:
|
case MSG_SHOW_SOURCE_PACKAGES:
|
||||||
{
|
{
|
||||||
BAutolock locker(fModel.Lock());
|
BAutolock locker(fModel.Lock());
|
||||||
@@ -358,6 +397,8 @@ MainWindow::StoreSettings(BMessage& settings) const
|
|||||||
|
|
||||||
settings.AddBool("show develop packages", fModel.ShowDevelopPackages());
|
settings.AddBool("show develop packages", fModel.ShowDevelopPackages());
|
||||||
settings.AddBool("show source packages", fModel.ShowSourcePackages());
|
settings.AddBool("show source packages", fModel.ShowSourcePackages());
|
||||||
|
|
||||||
|
settings.AddString("username", fModel.Username());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -401,8 +442,12 @@ MainWindow::_BuildMenu(BMenuBar* menuBar)
|
|||||||
BMenu* menu = new BMenu(B_TRANSLATE("Tools"));
|
BMenu* menu = new BMenu(B_TRANSLATE("Tools"));
|
||||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Refresh depots"),
|
menu->AddItem(new BMenuItem(B_TRANSLATE("Refresh depots"),
|
||||||
new BMessage(MSG_REFRESH_DEPOTS)));
|
new BMessage(MSG_REFRESH_DEPOTS)));
|
||||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Log in"),
|
menu->AddSeparatorItem();
|
||||||
|
menu->AddItem(new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
|
||||||
new BMessage(MSG_LOG_IN)));
|
new BMessage(MSG_LOG_IN)));
|
||||||
|
fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
|
||||||
|
new BMessage(MSG_LOG_OUT));
|
||||||
|
menu->AddItem(fLogOutItem);
|
||||||
menuBar->AddItem(menu);
|
menuBar->AddItem(menu);
|
||||||
|
|
||||||
// menu = new BMenu(B_TRANSLATE("Options"));
|
// menu = new BMenu(B_TRANSLATE("Options"));
|
||||||
@@ -858,3 +903,11 @@ MainWindow::_OpenLoginWindow()
|
|||||||
window->Show();
|
window->Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MainWindow::_UpdateAuthorization()
|
||||||
|
{
|
||||||
|
BString username(fModel.Username());
|
||||||
|
fLogOutItem->SetEnabled(username.Length() > 0);
|
||||||
|
fFilterView->SetUsername(username);
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,16 +72,19 @@ private:
|
|||||||
const char* message);
|
const char* message);
|
||||||
|
|
||||||
void _OpenLoginWindow();
|
void _OpenLoginWindow();
|
||||||
|
void _UpdateAuthorization();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilterView* fFilterView;
|
FilterView* fFilterView;
|
||||||
PackageListView* fPackageListView;
|
PackageListView* fPackageListView;
|
||||||
PackageInfoView* fPackageInfoView;
|
PackageInfoView* fPackageInfoView;
|
||||||
BSplitView* fSplitView;
|
BSplitView* fSplitView;
|
||||||
|
BMenuItem* fLogOutItem;
|
||||||
BMenuItem* fShowDevelopPackagesItem;
|
BMenuItem* fShowDevelopPackagesItem;
|
||||||
BMenuItem* fShowSourcePackagesItem;
|
BMenuItem* fShowSourcePackagesItem;
|
||||||
|
|
||||||
Model fModel;
|
Model fModel;
|
||||||
|
ModelListenerRef fModelListener;
|
||||||
PackageList fVisiblePackages;
|
PackageList fVisiblePackages;
|
||||||
|
|
||||||
bool fTerminating;
|
bool fTerminating;
|
||||||
|
|||||||
Reference in New Issue
Block a user