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

Evolution credentials portal #83

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install Dependencies
run: |
apt update
apt install -y libgranite-7-dev libgtk-4-dev meson valac
apt install -y libgranite-7-dev libgtk-4-dev libedataserver1.2-dev meson valac
- name: Build
run: |
meson build
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ glib_dep = dependency('glib-2.0')
gobject_dep = dependency('gobject-2.0')
gio_dep = dependency('gio-2.0')
granite_dep = dependency('granite-7')
libedataserver_dep = dependency('libedataserver-1.2')

gtk_deps = [
dependency('gtk4')
Expand Down
27 changes: 27 additions & 0 deletions src/ElementaryPortal/ElementaryPortal.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
public class ElementaryPortal : Object {
uint owner_id;

construct {
owner_id = GLib.Bus.own_name (
GLib.BusType.SESSION,
"org.freedesktop.portal.elementary",
GLib.BusNameOwnerFlags.ALLOW_REPLACEMENT | (opt_replace ? GLib.BusNameOwnerFlags.REPLACE : 0),
on_bus_acquired
);
}

~ElementaryPortal () {
GLib.Bus.unown_name (owner_id);
}

private void on_bus_acquired (DBusConnection connection, string name) {
PermissionStore.init (connection);

try {
connection.register_object ("/org/freedesktop/portal/elementary", new EvolutionCredentials.Portal (connection));
debug ("EvolutionCredentials Portal registered!");
} catch (Error e) {
critical ("Unable to register the object: %s", e.message);
}
}
}
134 changes: 134 additions & 0 deletions src/ElementaryPortal/EvolutionCredentials/Portal.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
[DBus (name = "org.freedesktop.portal.elementary.EvolutionCredentials")]
public class EvolutionCredentials.Portal : Object {
private const string TABLE = "evolution-credentials";
private const string ID = "evolution-credentials";

private const string PERMISSION_ALLOW = "allow";
private const string PERMISSION_FORBID = "forbid";
private const string PERMISSION_ASK = "ask";

private DBusConnection connection;
private E.SourceRegistry registry;

public Portal (DBusConnection connection) {
this.connection = connection;
get_registry.begin ();
}

private async void get_registry () {
try {
registry = yield new E.SourceRegistry (null);
} catch (Error e) {
critical ("EvolutionCredentials Portal not functional: Failed to get Evolution SourceRegistry: %s", e.message);
}
}

public async void get_credentials_for_account_uid (
string app_id,
string parent_window,
string account_uid,
string handle_token
) throws DBusError, IOError {
uint response = 2;
var request = new Request ();
var results = new HashTable<string, Variant> (str_hash, str_equal);

uint register_id;

try {
register_id = connection.register_object ("/org/freedesktop/portal/elementary/%s/%s".printf (app_id, handle_token), request);
} catch (Error e) {
warning ("Failed to register request object: %s", e.message);
throw new DBusError.OBJECT_PATH_IN_USE (e.message);
}

try {
var permissions = PermissionStore.get_permission (TABLE, ID, app_id);
switch (permissions[0]) {
case PERMISSION_ALLOW:
response = 0;
break;
case PERMISSION_FORBID:
response = 1;
break;
default:
break;
}
} catch (Error e) {
warning ("Failed to get permission: %s", e.message);
}

if (response == 2) {
var dialog = new Granite.MessageDialog.with_image_from_icon_name (
_("Allow %s to access your Online Accounts?"),
_("This is a valid reason"),
"dialog-warning",
Gtk.ButtonsType.NONE
);
dialog.add_button (_("Forbid"), 1);
var allow_button = dialog.add_button (_("Allow"), 0);
allow_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION);

dialog.response.connect ((_response) => {
string permission;

switch (_response) {
case 0:
response = 0;
permission = PERMISSION_ALLOW;
break;
case 1:
response = 1;
permission = PERMISSION_FORBID;
break;
default:
permission = PERMISSION_ASK;
break;
}

try {
PermissionStore.set_permission (TABLE, true, ID, app_id, { permission });
} catch (Error e) {
warning ("Failed to set permission for '%s': %s", app_id, e.message);
}

dialog.destroy ();
get_credentials_for_account_uid.callback ();
});

request.closed.connect (() => {
dialog.destroy ();
get_credentials_for_account_uid.callback ();
});

dialog.present ();

yield;
}

if (response == 0) {
try {
var credentials = yield lookup_credentials (account_uid);
results["credentials"] = credentials;
} catch (Error e) {
warning ("Credentials for account uid '%s' not found: %s", account_uid, e.message);
response = 2;
}
}

request.response (response, results);
connection.unregister_object (register_id);
}

private async string lookup_credentials (string account_uid) throws Error {
string? password;

var source = registry.ref_source (account_uid);
if (!yield source.lookup_password (null, out password)) {
throw new IOError.NOT_FOUND ("Password not found");
}

return password;
}

}
39 changes: 39 additions & 0 deletions src/ElementaryPortal/PermissionStore.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[DBus (name = "org.freedesktop.impl.portal.PermissionStore")]
public interface PermissionStore : Object {
public static PermissionStore permission_store;
public static void init (DBusConnection connection) {
try {
permission_store = connection.get_proxy_sync (
"org.freedesktop.impl.portal.PermissionStore",
"/org/freedesktop/impl/portal/PermissionStore"
);
} catch {
critical ("Cannot connect to PermissionStore dbus, elementary portal working with reduced functionality.");
}
}

public static void set_permission (
string table,
bool create,
string id,
string app_id,
string[] permissions
) throws DBusError, IOError {
permission_store._set_permission (table, create, id, app_id, permissions);
}

public static string[]? get_permission (string table, string id, string app_id) throws DBusError, IOError {
return permission_store._get_permission (table, id, app_id);
}

[DBus (name = "SetPermission")]
public abstract void _set_permission (
string table,
bool create,
string id,
string app_id,
string[] permissions
) throws DBusError, IOError;
[DBus (name = "GetPermission")]
public abstract string[]? _get_permission (string table, string id, string app_id) throws DBusError, IOError;
}
11 changes: 11 additions & 0 deletions src/ElementaryPortal/Request.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[DBus (name = "org.freedesktop.portal.Request")]
public class EvolutionCredentials.Request : Object {
public signal void response (uint response, HashTable<string, Variant> results);

[DBus (visible = false)]
public signal void closed ();

public void close () throws DBusError, IOError {
closed ();
}
}
3 changes: 3 additions & 0 deletions src/XdgDesktopPortalPantheon.vala
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ int main (string[] args) {
on_name_acquired,
() => { loop.quit (); }
);

new ElementaryPortal ();

loop.run ();
GLib.Bus.unown_name (owner_id);
return 0;
Expand Down
7 changes: 6 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ executable(
'AppChooser/Portal.vala',
'Background/NotificationRequest.vala',
'Background/Portal.vala',
'ElementaryPortal/ElementaryPortal.vala',
'ElementaryPortal/PermissionStore.vala',
'ElementaryPortal/Request.vala',
'ElementaryPortal/EvolutionCredentials/Portal.vala',
configure_file(input: 'Config.vala.in', output: '@BASENAME@', configuration: conf_data),
'ExternalWindow.vala',
'XdgDesktopPortalPantheon.vala',
Expand All @@ -17,7 +21,8 @@ executable(
gio_dep,
granite_dep,
gtk_deps,
x11_dep
x11_dep,
libedataserver_dep
],
install: true,
install_dir: libexecdir
Expand Down