FrostCo / AdvancedProfanityFilter

A browser extension to filter profanity from webpages
GNU General Public License v3.0
159 stars 26 forks source link

Need ability to deploy extension with pre-configured settings/password lock enabled #525

Closed TLeatherland closed 4 months ago

TLeatherland commented 7 months ago

:loudspeaker: Problem

I work in a school and want to deploy this through the Google Admin console to all the students. Problem is when deploying it currently, it just uses default settings and is password unlocked, so kids can just turn it off again/disable it at will.

:microscope: Solution

Need a way to deploy a pre-configured and password locked version or to specify a config file to be imported automatically at launch

Any suggestions/possible workarounds?

richardfrost commented 7 months ago

Hi @TLeatherland, thanks for your interest!

I haven't had the opportunity to use Google Admin Console, so I'm not sure exactly what capabilities it has. I'm assuming you have the ability to remotely install extensions to browsers, is that right? Is there also a way that you can push config as well? Extensions use chrome.storage to keep their config. I am thinking if you have a way to push a chrome.storage.local config (JSON) for the extension when you install it that should be good to go. If you have a test/dev environment that you can share I'd be happy to take a look around at it.

TLeatherland commented 7 months ago

Hi @richardfrost, thanks for the reply! I can remotely install extensions to browsers however it doesn't let me specify a config to push with them. What I can do though is deploy custom extensions - i.e. I could edit the unpacked extension files then repack and deploy that version. Just wondering if theres a particular file where the default config is stored/could be altered?

TLeatherland commented 7 months ago

I think I'd be able to push a config if you could integrate Google's managed config api - https://chromeos.dev/en/enterprise/web-managed-config

richardfrost commented 7 months ago

@TLeatherland thanks for the additional info. I think if we can use the managed config it would be best, because having to load an unpacked extension could be difficult to keep it up-to-date (if you care to).

I took a stab at making a build that can read in config overrides, but I don't have a way to test it and see how it works or what it does.

For starters, maybe just try the following managed config:

{
  "password": "1234"
}

With that set, when you click to open the options for the extension it should prompt for a password.

Let me know how it goes when you have a chance to test it out. If this does work (or works with a few modifications) I think this would be a good path forward, and could be included in the official release so you wouldn't have to try and maintain a separate version.

TLeatherland commented 7 months ago

Amazing, you work fast! I uploaded your provided zip to my Chrome Web Store developer dashboard as a private extension, then deployed it with the admin console once it had completed review. Unfortunately that doesn't seem to have worked, still no option given to add a managed config in the admin console, cant figure out a way to push password. I got in touch with Google support to see if they could offer any advice - this is what they had to say:

'To enable the option for your Chrome extension to be deployed with a managed configuration JSON file, please provide these helpful details to the developer:

  1. Familiarize with Managed Configuration API: Thoroughly understand the Managed Configuration API and its capabilities. Read the documentation, explore examples, and familiarize yourself with the API's structure and terminology.

  2. Update Extension Version: Ensure your extension is updated to a version that supports the Managed Configuration API. The API was introduced in a specific version of the Chrome extension APIs, and only extensions updated to that or a later version will be able to utilize it.

  3. Declare Extension Permissions: Specify the necessary permissions for managed configurations in your extension's manifest file. These permissions allow the extension to access and utilize the managed configuration data.

  4. Implement Managed Configuration Logic: Implement the logic for handling managed configuration data within your extension's code. This includes parsing the JSON configuration file, validating the data, and applying the configuration settings to the extension's behavior.

  5. Create Managed Configuration JSON File: Create the managed configuration JSON file that will be deployed alongside your extension. This file should follow the expected schema and contain the configuration settings you want to apply to the extension.

  6. Test Managed Configuration Functionality: Thoroughly test the managed configuration functionality of your extension. Ensure the extension correctly loads, parses, and applies the managed configuration settings.

  7. Document Managed Configuration Usage: Provide clear documentation for users and administrators on how to deploy and manage the extension with a managed configuration JSON file. This documentation should include instructions, examples, and troubleshooting steps.

  8. Release Updated Extension: Once the managed configuration functionality is fully implemented and tested, release an updated version of your extension. Include the updated extension manifest file, the managed configuration JSON file, and the updated documentation.'

Don't know if thats any help to you?

Just want to say I massively appreciate you taking the time to try implement this, especially given you don't even have proper workspace access/ability to test it.

I will say - if you can get this managed config/chrome admin deployment stuff to work I do think you could charge for the extension. It'd be a massive boon for education customers.

richardfrost commented 7 months ago

Thanks @TLeatherland! I try to help out when I can.

And thank you for all those additional details. I think I understand the process a bit more now and have another attempt for you to try:

chrome-mv3-v3.2.5-web_managed_config.zip

This one only supports the password config, but it should be enough to see if it works. If it does, I can add support for most of the other config options.

Thanks again for being willing to help out and test this. I would definitely love to get it working for you, and hopefully others could find it useful too!

TLeatherland commented 7 months ago

Definitely making progress but not quite there - when deploying this new build it now has password enabled by default (set to '1234'), however I still can't change the set password from within the admin console.

The previous build looked like this when deployed in the admin console - 3 2 4

The new build looks like this - 3 2 5

So whatever you've done has successfully added that 'Policy for Extensions' section, however this doesn't seem to work how we want/I can't use it to change the set password (with the above entered, we'd expect password to become 'cheese', but it remains '1234').

Its also different to the 'managed config' section which still isn't showing. That should look like this - managedconfig

I can see in manifest.json you've got storage/managed_schema set to schema.json - just wondering where thats actually pulling/reading '1234' from as the set password?

richardfrost commented 7 months ago

Well, hopefully a step in the right direction then! The extension shouldn't be setting the password to '1234', so I'm not sure where it would be getting that value from. If you open the root of the .zip file you'll see the referenced schema.json file, but as the name implies its just the schema, not any values.

Not sure how you are testing it, but could you make sure there is a clean environment? Possibly removing the extension from the machine and then re-installing it?

Here is a newer build with some logging that might gives us some more details:

chrome-mv3-v3.2.6-managed_config_with_logging.zip

With this build when you open the option's page, open up the web developer tools and look in the console for the message starting with:

Managed Config:

It should show us what values its getting from the policy. Could you share what that is showing? (If the logging doesn't happen at first, try just refreshing the options page).

As for the naming, from what I can see in the documentation they actually do call it "Extension policies", so that may be correct when dealing with extensions? On that last screenshot is the "Managed configuration" from another extension, or a different app/website? Just wondering if they are using different terminology based on what the type of application you are configuring.

TLeatherland commented 7 months ago

How curious. For testing I tried both installing like a normal extension just on my device, and also deploying through admin console to an OU with my device in it. In both cases it was a clean environment and the old extension was removed first. In both cases the extension by default had password enabled and set to '1234'.

I think you are correct with regard to terminology - i.e. that last screenshot of 'managed configuration' is from a web-app instead of an extension. I think web-apps and play store apps get 'managed configuration', and extensions get 'Policy for extensions'.

Just waiting for Google to re-review/accept this new build with logging, then will test it and report back.

Just to be clear though, is the expectation that I should be able to enter this into the 'policy for extensions' field - password And doing so should set the password to 'cheese'? Is that the correct formatting?

richardfrost commented 7 months ago

Yeah, that is definitely strange, because it has be getting 1234 from somewhere.. just not sure where. Hopefully the extra logging will help a bit.

Yes, that does look correct to me. I would expect that to set the password to cheese if it is being applied correctly.

richardfrost commented 7 months ago

Not sure about this @TLeatherland, but its possible it may be expecting a different format for the policies according to this.

Maybe try:

{
  "password": {
    "value": "cheese"
  }
}

Not sure on casing requirements, but value might need to be Value. You might have to try both variations. I believe password should be lower case as defined in the schema.json file.

TLeatherland commented 7 months ago

Great Success!! Went for above format with Value capitalised and it worked first try, deployed with password set to cheese - logging works too. But I'm assuming that means the previous 3.2.5 build without logging also should work, I just had the formatting wrong for the extension policy entry?

Take it next step is to construct a schema file that maps to all different config settings - might it be possible to make it circular/match up with the config file that can already be exported through the options page?
Screenshot 2023-11-30 21 36 08

Such that I could deploy the extension to my own machine, configure my desired settings within the extension ui, export the json, and then just copy and paste its contents into the admin console 'Policy for Extensions' box when deploying to everyone else?

(no worries if thats too much/not feasible with how schemas have to be constructed, and thanks again for all the work)

richardfrost commented 7 months ago

Awesome! Yeah, that seems to indicate 3.2.5 would also work.

I've put together a new build here: chrome-mv3-v3.2.7.zip

This one includes a lot more policy options (see the schema.json for a full list). I'm not positive this will work since I can't test, but I did add a new hidden export method to try and create a policy file out of your current config. To use it, open the browser's dev tools and set this variable in the JS console:

managedConfig = true;

Once that is set, just go to the config tab and check the box by "Inline editor". That variable won't stick around, so if you want to get back to the "regular" mode you can either set it to false, or just refresh the page.

I'm not sure on your use case, but right now the support for this managed policy config is pretty much all-or-nothing. For instance, even if a student (or another user) were able to get ahold of the password, as long as there is at least 1 policy value set, it will always use either the policy value, or if its missing it will use the default value in the extension. It will never look to the local or sync storage for config. That means no one will be able to customize their settings. Not sure if that's desired, or if we need to work out more of how it should work. I'm sure we could work out a pretty good solution if you want more flexibility.

At least it seems we have proved that it is possible. So now hopefully we can work on figuring out how to make it practical to use and deploy.

TLeatherland commented 7 months ago

Have got almost everything working This is my current config and its all working as intended -

{
  "censorCharacter": {
    "Value": "*"
  },
  "censorFixedLength": {
    "Value": 0
  },
  "defaultWordMatchMethod": {
    "Value": 1
  },
  "defaultWordRepeat": {
    "Value": 1
  },
  "defaultWordSeparators": {
    "Value": 1
  },
  "filterMethod": {
    "Value": 0
  },
  "password": {
    "Value": "bacon"
  },
  "preserveFirst": {
    "Value": false
  },
  "preserveLast": {
    "Value": false
  },
  "showCounter": {
    "Value": false
  },
  "showSummary": {
    "Value": false
  },
  "wordlistId": {
    "Value": 0
  },
  "wordlists": {
    "Value": [
      "Wordlist 1",
      "Wordlist 2",
      "Wordlist 3",
      "Wordlist 4",
      "Wordlist 5",
      "Wordlist 6"
    ]
  },
  "wordlistsEnabled": {
    "Value": true
  }
}

The issue I've reached is that I can't add additional/custom words to the word list. I've tried adding this code for all desired words -

{
  "words": {
    "RUDEWORD1": {
      "lists": [1],
      "matchMethod": 0,
      "repeat": 1,
      "separators": 0,
      "sub": ""
    },
    "RUDEWORD2": {
      "lists": [1],
      "matchMethod": 0,
      "repeat": 0,
      "separators": 0,
      "sub": ""
    }
  }
}

but doing so seems to stop the rest of the config working (i.e. If I add the words section, the extension will ignore it and any other changes and just use the previous settings)

The current 'all or nothing' way its set up works for me, can deploy same settings to all students after configuring to liking on my own device. Just need to be able to update/add to the list of filtered words which is what I'm currently struggling with

richardfrost commented 7 months ago

@TLeatherland im glad it's getting so close! Could you share what the managed policies look like? (it's still JSON, but in that format you add in the Google admin console).

TLeatherland commented 7 months ago

Sorry, the above is how its formatted in the Google admin console i.e. my last post is the same as whats in managed policies pol

richardfrost commented 7 months ago

@TLeatherland Sorry I was wanting to confirm what the "words" looked like that you were adding for the policy. I'm thinking the syntax for the words policy might be a bit off. If its invalid for the words, I do think Google will not use any of the policies.

TLeatherland commented 7 months ago

When I tried adding the 'words' bit I also did it same as above, just tacked on the end like this -

{
  "wordlistsEnabled": {
    "Value": true
  },
  "words": {
    "RUDEWORD1": {
    "lists": [1],
    "matchMethod": 0,
    "repeat": 1,
    "separators": 0,
    "sub": ""
  },
  "RUDEWORD2": {
    "lists": [1],
    "matchMethod": 0,
    "repeat": 0,
    "separators": 0,
    "sub": ""
  }
}

Do you have any idea what the correct syntax for the words section would be then?

richardfrost commented 7 months ago

I am having a hard time finding any documentation for how an object is supposed to look in their documentation, so it may take some trial and error to get it right. Here is my first guess:

{
  "words": {
    "Value": {
      "RUDEWORD1": {
        "lists": [1],
        "matchMethod": 0,
        "repeat": 1,
        "separators": 0,
        "sub": ""
      },
      "RUDEWORD2": {
        "lists": [1],
        "matchMethod": 0,
        "repeat": 0,
        "separators": 0,
        "sub": ""
      }
    }
  }
}
richardfrost commented 7 months ago

@TLeatherland Hey, just wanted to make sure you saw my last comment. No worries if you're out or otherwise busy. I just realized I forgot to include your name in my last comment.

TLeatherland commented 7 months ago

Hi Richard, sorry for the delayed response, been off work ill past few days. Will test out the above formatting today and get back to you.

Aside from that, only other thing would be is it possible to stop the extension options page automatically opening in a new tab when the browser is launched/extension is first installed? The junior school devices are set to wipe on sign out so every time they login it gets reinstalled and then opens the options page when they launch chrome. Its minor, but kids are complaining

Thanks again!

TLeatherland commented 7 months ago

Can confirm the syntax you've provided above does indeed work to add words to the list! :) Well done, and thankyou!

richardfrost commented 6 months ago

@TLeatherland that's awesome news! I have a new build here that should allow you to suppress the extension from opening automatically on installation/deployment that I'd love for you to try.

chrome-mv3-v3.2.8-managed_config_supress_open_on_install.zip

Also, could I have you follow the instructions here and see if they are working for you as expected? (for example, try exporting the config from the extension and without any modifications to the exported text see if it works)? I'm curious if "value" will work, or if it needs to be capitalized for example. It should also correctly export words so you shouldn't need to change anything with it. I want to try and make it as streamlined as possible.

Thanks again for your willingness to help me work through this with you.

richardfrost commented 5 months ago

Hi @TLeatherland, just wanted to check in with you and see how things are going? I have released version 3.3.0 which should include what we worked on, so if you do want to use the official version instead of this zip file give it a try and let me know how it goes. If you have trouble with it I'm happy to work with you on getting it resolved.

richardfrost commented 4 months ago

Hey @TLeatherland, if you do get a chance to test it anymore let me know how it goes. Otherwise, I'm going to close this. Feel free to respond here, or open another issue if you need to.