Merge pull request #4 from endlessm/T23999-oars-storage
T23999 Store OARS filter
This commit is contained in:
commit
ebb892092f
|
@ -31,5 +31,33 @@
|
|||
<annotation name="org.freedesktop.Accounts.DefaultValue"
|
||||
value="(false, [])"/>
|
||||
</property>
|
||||
|
||||
<!--
|
||||
oars-filter:
|
||||
|
||||
A filter for which applications the user can see in app lists and install.
|
||||
This is intended to be set by administrators and read by users, rather
|
||||
than being editable by the user themselves.
|
||||
|
||||
It’s a two-tuple of the rating type, and a dictionary of rating sections
|
||||
and values. The type gives the rating scheme in use — currently only
|
||||
`oars-1.0` is supported.
|
||||
|
||||
Each dictionary entry is a mapping from an OARS section to the
|
||||
most severe value for it which the user is allowed to see (inclusive). Any
|
||||
app with a more severe value for any section must not be listed or
|
||||
installable by the user.
|
||||
|
||||
An empty dictionary means that no OARS filtering is to be performed for
|
||||
the user.
|
||||
|
||||
This setting is essentially equivalent to the `content_rating` dictionary
|
||||
in AppStream data:
|
||||
https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-content_rating.
|
||||
-->
|
||||
<property name="oars-filter" type="(sa{ss})" access="readwrite">
|
||||
<annotation name="org.freedesktop.Accounts.DefaultValue"
|
||||
value="('oars-1.0', @a{ss} {})"/>
|
||||
</property>
|
||||
</interface>
|
||||
</node>
|
|
@ -95,6 +95,23 @@ def __lookup_user_id_or_error(user):
|
|||
raise SystemExit(EXIT_INVALID_OPTION)
|
||||
|
||||
|
||||
def __oars_value_to_string(value):
|
||||
"""Convert an EosParentalControls.AppFilterOarsValue to a human-readable
|
||||
string."""
|
||||
mapping = {
|
||||
EosParentalControls.AppFilterOarsValue.UNKNOWN: "unknown",
|
||||
EosParentalControls.AppFilterOarsValue.NONE: "none",
|
||||
EosParentalControls.AppFilterOarsValue.MILD: "mild",
|
||||
EosParentalControls.AppFilterOarsValue.MODERATE: "moderate",
|
||||
EosParentalControls.AppFilterOarsValue.INTENSE: "intense",
|
||||
}
|
||||
|
||||
try:
|
||||
return mapping[value]
|
||||
except KeyError:
|
||||
return "invalid (OARS value {})".format(value)
|
||||
|
||||
|
||||
def command_get(user, quiet=False, interactive=True):
|
||||
"""Get the app filter for the given user."""
|
||||
user_id = __lookup_user_id_or_error(user)
|
||||
|
@ -121,6 +138,17 @@ def command_check(user, path, quiet=False, interactive=True):
|
|||
raise SystemExit(EXIT_PATH_NOT_ALLOWED)
|
||||
|
||||
|
||||
def command_oars_section(user, section, quiet=False, interactive=True):
|
||||
"""Get the value of the given OARS section for the given user, according
|
||||
to their OARS filter."""
|
||||
user_id = __lookup_user_id_or_error(user)
|
||||
app_filter = __get_app_filter_or_error(user_id, interactive)
|
||||
|
||||
value = app_filter.get_oars_value(section)
|
||||
print('OARS section ‘{}’ for user {} has value ‘{}’'.format(
|
||||
section, user_id, __oars_value_to_string(value)))
|
||||
|
||||
|
||||
def main():
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
|
@ -164,6 +192,18 @@ def main():
|
|||
parser_check.add_argument('path',
|
||||
help='path to a program to check')
|
||||
|
||||
# ‘oars-section’ command
|
||||
parser_oars_section = subparsers.add_parser('oars-section',
|
||||
parents=[common_parser],
|
||||
help='get the value of a '
|
||||
'given OARS section')
|
||||
parser_oars_section.set_defaults(function=command_oars_section)
|
||||
parser_oars_section.add_argument('user', default='', nargs='?',
|
||||
help='user ID or username to get the '
|
||||
'OARS filter for (default: current '
|
||||
'user)')
|
||||
parser_oars_section.add_argument('section', help='OARS section to get')
|
||||
|
||||
# Parse the command line arguments and run the subcommand.
|
||||
args = parser.parse_args()
|
||||
args_dict = dict((k, v) for k, v in vars(args).items() if k != 'function')
|
||||
|
|
|
@ -56,6 +56,8 @@ struct _EpcAppFilter
|
|||
|
||||
gchar **app_list; /* (owned) (array zero-terminated=1) */
|
||||
EpcAppFilterListType app_list_type;
|
||||
|
||||
GVariant *oars_ratings; /* (type a{ss}) (owned) */
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (EpcAppFilter, epc_app_filter,
|
||||
|
@ -101,6 +103,7 @@ epc_app_filter_unref (EpcAppFilter *filter)
|
|||
if (filter->ref_count <= 0)
|
||||
{
|
||||
g_strfreev (filter->app_list);
|
||||
g_variant_unref (filter->oars_ratings);
|
||||
g_free (filter);
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +162,50 @@ epc_app_filter_is_path_allowed (EpcAppFilter *filter,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if @error is a D-Bus remote error mataching @expected_error_name. */
|
||||
/**
|
||||
* epc_app_filter_get_oars_value:
|
||||
* @filter: an #EpcAppFilter
|
||||
* @oars_section: name of the OARS section to get the value from
|
||||
*
|
||||
* Get the value assigned to the given @oars_section in the OARS filter stored
|
||||
* within @filter. If that section has no value explicitly defined,
|
||||
* %EPC_APP_FILTER_OARS_VALUE_UNKNOWN is returned.
|
||||
*
|
||||
* This value is the most intense value allowed for apps to have in this
|
||||
* section, inclusive. Any app with a more intense value for this section must
|
||||
* be hidden from the user whose @filter this is.
|
||||
*
|
||||
* Returns: an #EpcAppFilterOarsValue
|
||||
* Since: 0.1.0
|
||||
*/
|
||||
EpcAppFilterOarsValue
|
||||
epc_app_filter_get_oars_value (EpcAppFilter *filter,
|
||||
const gchar *oars_section)
|
||||
{
|
||||
const gchar *value_str;
|
||||
|
||||
g_return_val_if_fail (filter != NULL, EPC_APP_FILTER_OARS_VALUE_UNKNOWN);
|
||||
g_return_val_if_fail (filter->ref_count >= 1,
|
||||
EPC_APP_FILTER_OARS_VALUE_UNKNOWN);
|
||||
g_return_val_if_fail (oars_section != NULL && *oars_section != '\0',
|
||||
EPC_APP_FILTER_OARS_VALUE_UNKNOWN);
|
||||
|
||||
if (!g_variant_lookup (filter->oars_ratings, oars_section, "&s", &value_str))
|
||||
return EPC_APP_FILTER_OARS_VALUE_UNKNOWN;
|
||||
|
||||
if (g_str_equal (value_str, "none"))
|
||||
return EPC_APP_FILTER_OARS_VALUE_NONE;
|
||||
else if (g_str_equal (value_str, "mild"))
|
||||
return EPC_APP_FILTER_OARS_VALUE_MILD;
|
||||
else if (g_str_equal (value_str, "moderate"))
|
||||
return EPC_APP_FILTER_OARS_VALUE_MODERATE;
|
||||
else if (g_str_equal (value_str, "intense"))
|
||||
return EPC_APP_FILTER_OARS_VALUE_INTENSE;
|
||||
else
|
||||
return EPC_APP_FILTER_OARS_VALUE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Check if @error is a D-Bus remote error matching @expected_error_name. */
|
||||
static gboolean
|
||||
bus_remote_error_matches (const GError *error,
|
||||
const gchar *expected_error_name)
|
||||
|
@ -325,6 +371,9 @@ get_app_filter_cb (GObject *obj,
|
|||
g_autoptr(EpcAppFilter) app_filter = NULL;
|
||||
gboolean is_whitelist;
|
||||
g_auto(GStrv) app_list = NULL;
|
||||
const gchar *content_rating_kind;
|
||||
g_autoptr(GVariant) oars_variant = NULL;
|
||||
g_autoptr(GHashTable) oars_map = NULL;
|
||||
|
||||
GetAppFilterData *data = g_task_get_task_data (task);
|
||||
result_variant = g_dbus_connection_call_finish (connection, result, &local_error);
|
||||
|
@ -350,6 +399,25 @@ get_app_filter_cb (GObject *obj,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!g_variant_lookup (properties, "oars-filter", "(&s@a{ss})",
|
||||
&content_rating_kind, &oars_variant))
|
||||
{
|
||||
/* Default value. */
|
||||
content_rating_kind = "oars-1.0";
|
||||
oars_variant = g_variant_new ("@a{ss} {}");
|
||||
}
|
||||
|
||||
/* Check that the OARS filter is in a format we support. Currently, that’s
|
||||
* only oars-1.0. */
|
||||
if (!g_str_equal (content_rating_kind, "oars-1.0"))
|
||||
{
|
||||
g_task_return_new_error (task, EPC_APP_FILTER_ERROR,
|
||||
EPC_APP_FILTER_ERROR_INVALID_DATA,
|
||||
_("OARS filter for user %u has an unrecognized kind ‘%s’"),
|
||||
data->user_id, content_rating_kind);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Success. Create an #EpcAppFilter object to contain the results. */
|
||||
app_filter = g_new0 (EpcAppFilter, 1);
|
||||
app_filter->ref_count = 1;
|
||||
|
@ -357,6 +425,7 @@ get_app_filter_cb (GObject *obj,
|
|||
app_filter->app_list = g_steal_pointer (&app_list);
|
||||
app_filter->app_list_type =
|
||||
is_whitelist ? EPC_APP_FILTER_LIST_WHITELIST : EPC_APP_FILTER_LIST_BLACKLIST;
|
||||
app_filter->oars_ratings = g_steal_pointer (&oars_variant);
|
||||
|
||||
g_task_return_pointer (task, g_steal_pointer (&app_filter),
|
||||
(GDestroyNotify) epc_app_filter_unref);
|
||||
|
|
|
@ -33,6 +33,8 @@ G_BEGIN_DECLS
|
|||
* @EPC_APP_FILTER_ERROR_INVALID_USER: Given user ID doesn’t exist
|
||||
* @EPC_APP_FILTER_ERROR_PERMISSION_DENIED: Not authorized to query the app
|
||||
* filter for the given user
|
||||
* @EPC_APP_FILTER_ERROR_INVALID_DATA: The data stored in the app filter for
|
||||
* a user is inconsistent or invalid
|
||||
*
|
||||
* Errors which can be returned by epc_get_app_filter_async().
|
||||
*
|
||||
|
@ -42,11 +44,38 @@ typedef enum
|
|||
{
|
||||
EPC_APP_FILTER_ERROR_INVALID_USER,
|
||||
EPC_APP_FILTER_ERROR_PERMISSION_DENIED,
|
||||
EPC_APP_FILTER_ERROR_INVALID_DATA,
|
||||
} EpcAppFilterError;
|
||||
|
||||
GQuark epc_app_filter_error_quark (void);
|
||||
#define EPC_APP_FILTER_ERROR epc_app_filter_error_quark ()
|
||||
|
||||
/**
|
||||
* EpcAppFilterOarsValue:
|
||||
* @EPC_APP_FILTER_OARS_VALUE_UNKNOWN: Unknown value for the given
|
||||
* section.
|
||||
* @EPC_APP_FILTER_OARS_VALUE_NONE: No rating for the given section.
|
||||
* @EPC_APP_FILTER_OARS_VALUE_MILD: Mild rating for the given section.
|
||||
* @EPC_APP_FILTER_OARS_VALUE_MODERATE: Moderate rating for the given
|
||||
* section.
|
||||
* @EPC_APP_FILTER_OARS_VALUE_INTENSE: Intense rating for the given
|
||||
* section.
|
||||
*
|
||||
* Rating values of the intensity of a given section in an app or game.
|
||||
* These are directly equivalent to the values in the #AsContentRatingValue
|
||||
* enumeration in libappstream.
|
||||
*
|
||||
* Since: 0.1.0
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
EPC_APP_FILTER_OARS_VALUE_UNKNOWN,
|
||||
EPC_APP_FILTER_OARS_VALUE_NONE,
|
||||
EPC_APP_FILTER_OARS_VALUE_MILD,
|
||||
EPC_APP_FILTER_OARS_VALUE_MODERATE,
|
||||
EPC_APP_FILTER_OARS_VALUE_INTENSE,
|
||||
} EpcAppFilterOarsValue;
|
||||
|
||||
/**
|
||||
* EpcAppFilter:
|
||||
*
|
||||
|
@ -72,6 +101,9 @@ uid_t epc_app_filter_get_user_id (EpcAppFilter *filter);
|
|||
gboolean epc_app_filter_is_path_allowed (EpcAppFilter *filter,
|
||||
const gchar *path);
|
||||
|
||||
EpcAppFilterOarsValue epc_app_filter_get_oars_value (EpcAppFilter *filter,
|
||||
const gchar *oars_section);
|
||||
|
||||
void epc_get_app_filter_async (GDBusConnection *connection,
|
||||
uid_t user_id,
|
||||
gboolean allow_interactive_authorization,
|
||||
|
|
Loading…
Reference in New Issue