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

Read Discord Groups #390

Closed
kousu opened this issue Jan 24, 2023 · 18 comments
Closed

Read Discord Groups #390

kousu opened this issue Jan 24, 2023 · 18 comments

Comments

@kousu
Copy link

kousu commented Jan 24, 2023

This plugin is really useful! Really got my team onboard with using NextCloud, fast.

It doesn't seem to be able to read Discord Roles though. This seems to be the code that does that:

$response = $this->apiRequest('users/@me');
$data = new Data\Collection($response);
if (!$data->exists('id')) {
throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
}
// Makes display name more unique.
$displayName = $data->get('username') ?: $data->get('login');
if ($discriminator = $data->get('discriminator')) {
$displayName .= "#{$discriminator}";
}
$userProfile = new User\Profile();
$userProfile->identifier = $data->get('id');
$userProfile->displayName = $displayName;
$userProfile->email = $data->get('email');

Is there interest in mapping Roles to NextCloud Groups?

@pktiuk
Copy link
Contributor

pktiuk commented Feb 13, 2023

I would be interested in this feature for my organization, but I am aware that doing it properly could be a bit complicated.

Such functionality would need some kind of mapping configuration (which Discord role should be mapped to which NC group)

@kousu
Copy link
Author

kousu commented Feb 14, 2023

Some notes towards a patch!

The existing call to

$response = $this->apiRequest('users/@me');

reads the user object, which is global across Discord (API docs!), but roles are attached to servers (aka guilds) (API docs!). Which means a couple of things:

  1. This feature is only going to make sense if you use "Allow login only for specified guilds" and then it like, loops over those and reads them.

    I'm not sure how the guild ID makes it from the settings page

    Screert

    over into the plugin so I don't know how I could check this; it doesn't seem to be used in hybridauth/src/Provider/Discord.php, that's for sure.

  2. Granting permission is tricky. So far I've only gotten 401 Unauthorizeds.

    https://stackoverflow.com/questions/63234909/get-roles-of-current-user-in-discord-server#63235124 and https://stackoverflow.com/questions/69518877/discord-oauth2-getting-user-roles-from-exact-guild explain what I'm missing at a theoretical level, but left out the details of what you actually need to click in https://discord.com/developers/applications to make this work.

    I'm pretty unclear how to set this up. The default plugin setup doesn't require creating a bot user -- because it only has to read the global Discord /user/@me API -- but reading guild-specific data is going to require a bot, and that the bot is a member of the guild, and then that it either has the guilds.members.read OAuth2 scope, or maybe the GUILD_MEMBERS intent, whatever that is.

Here's some code that should do the trick, if I could figure out how to read the guild ID and could get the permissions to work

        # https://discord.com/developers/docs/resources/guild#get-guild-member
        $guild_id = "??????????";
        $guild_response = $this->apiRequest('guilds/' . $guild_id . '/members/' . $data->get('id') );
        $guild_data = new Data\Collection($guild_response);
        if (!$guild_data->exists('roles')) {
            throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
        }
        $userProfile->data['groups'] = $guild_data->get('roles');

@kousu
Copy link
Author

kousu commented Feb 14, 2023

Such functionality would need some kind of mapping configuration (which Discord role should be mapped to which NC group)

My half-finished patch above doesn't do any mapping. Looking ahead, the Custom OpenID Connect and Custom Discourse providers have this mapping button in the UI:

Screenshot 2023-02-14 at 02-08-41 Social login

which seem to be implemented like this:

if (null !== $groups = $this->getGroups($data)) {
$userProfile->data['groups'] = $groups;
}
if ($groupMapping = $this->config->get('group_mapping')) {
$userProfile->data['group_mapping'] = $groupMapping;
}

if (null !== $groups = $userProfile->data['groups']) {
$userProfile->data['groups'] = $this->strToArray($groups);
}
if ($groupMapping = $this->config->get('group_mapping')) {
$userProfile->data['group_mapping'] = $groupMapping;
}

I think for my first draft I would be happy if I could just get the groups read in at all!

kousu added a commit to kousu/nextcloud-social-login that referenced this issue Feb 14, 2023
@kousu
Copy link
Author

kousu commented Feb 14, 2023

I have a patch in ^. Do you think you're brave enough to try it out, @pktiuk ?

@pktiuk
Copy link
Contributor

pktiuk commented Feb 14, 2023

IDK how to run this kind of patch. (I am not an advanced NC user).

@kousu
Copy link
Author

kousu commented Feb 14, 2023

I'm not 100% sure how to collaborate with this sort of thing. I am guessing my way through as well.

What I know is that the contents of this repo seem to have been installed directly (including even non-functional files like CHANGELOG.md) to my nextcloud's apps/sociallogin/ folder:

www-data@org:~/nextcloud/apps/sociallogin$ pwd
/var/www/nextcloud/apps/sociallogin
www-data@org:~/nextcloud/apps/sociallogin$ ls -la
total 108
drwxr-xr-x 10 www-data www-data  4096 Feb 14 01:03 .
drwxr-xr-x 65 www-data www-data  4096 Feb  4 05:23 ..
drwxr-xr-x  5 www-data www-data  4096 Jan 23 23:49 3rdparty
-rw-r--r--  1 www-data www-data 21905 Jan 23 23:49 CHANGELOG.md
-rw-r--r--  1 www-data www-data 34520 Jan 23 23:49 COPYING
-rw-r--r--  1 www-data www-data  5211 Jan 23 23:49 README.md
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 appinfo
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 css
drwxr-xr-x  3 www-data www-data  4096 Jan 23 23:49 img
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 js
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 l10n
drwxr-xr-x 10 www-data www-data  4096 Jan 23 23:49 lib
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 templates

So in theory you should be able to replace it just by cloning this repo into the right place:

cd path/to/your/nextcloud/
cd apps
mv sociallogin sociallogin.disabled
# install my patch
git clone -b discord-roles https://github.com/kousu/nextcloud-social-login.git sociallogin  
cd ..
# nextcloud detects the change and forces this to run to recreate any needed database tables
php ./occ upgrade

and to downgrade again it looks like this works:

cd apps
mv sociallogin sociallogin.kousu
mv sociallogin.disabled sociallogin
cd ..
php ./occ upgrade

I would really appreciate some feedback on this if you are willing to help. The more feedback the faster it's going to be working and the sooner @zorn-v will see that there's both a need and a solution.

@pktiuk
Copy link
Contributor

pktiuk commented Feb 15, 2023

I will try to launch it tomorrow.

@pktiuk
Copy link
Contributor

pktiuk commented Feb 18, 2023

I got Error:
obraz

[index] Error: Exception: Undefined constant "OCA\SocialLogin\Service\allowedGuilds" in file '/var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php' line 419 at <<closure>>

0. /var/www/html/lib/private/AppFramework/App.php line 172
   OC\AppFramework\Http\Dispatcher->dispatch(OCA\SocialLogin\ ... {}, "oauth")
1. /var/www/html/lib/private/Route/Router.php line 298
   OC\AppFramework\App::main("OCA\\SocialLogi ... r", "oauth", OC\AppFramework\ ... {}, ["discord","sociallogin.login.oauth"])
2. /var/www/html/lib/base.php line 1047
   OC\Route\Router->match("/apps/sociallogin/oauth/discord")
3. /var/www/html/index.php line 36
   OC::handleRequest()

GET /apps/sociallogin/oauth/discord?code=pDdWS6wcbjpOOFV0JQDXG30jv5V7qm&state=HA-UOV31RMWBCTXL8YJQIFA2KH74EZ6ND90PG5S
from 37.225.92.137 at 2023-02-18T19:45:32+00:00

@kousu
Copy link
Author

kousu commented Feb 18, 2023 via email

@pktiuk
Copy link
Contributor

pktiuk commented Feb 18, 2023

This is how my config looks like:
obraz
Brak means None

@zorn-v
Copy link
Owner

zorn-v commented Feb 19, 2023

Error: Exception: Undefined constant "OCA\SocialLogin\Service\allowedGuilds"

You just missed $ char somewhere, so allowedGuilds considered as constant.

@kousu
Copy link
Author

kousu commented Feb 19, 2023

Right. Obviously. 😰 I don't write PHP that often. fixed: ac5d3df

I'm a little confused how I didn't catch this. I have this code deployed on my server and I went to meetings and saw people logging in with it.

Anyway it's updated. Sorry for the trouble @pktiuk, would you run git pull to try again when you have a moment? Thanks!

@pktiuk
Copy link
Contributor

pktiuk commented Feb 19, 2023

image
There is no group at all.

I also got an error, but it could be caused by not restarting NC correctly (after restarting container I could log in)

[PHP] Error: Error: exif_read_data(): File not supported at /var/www/html/lib/private/Metadata/Provider/ExifProvider.php#59 at <<closure>>

 0. <<closure>>
    OC\Log\ErrorHandler::onError(2, "exif_read_data(): File not supported", "/var/www/html/l ... p", 59)
 1. /var/www/html/lib/private/Metadata/Provider/ExifProvider.php line 59
    exif_read_data(null, "ANY_TAG", true)
 2. /var/www/html/lib/private/Metadata/MetadataManager.php line 68
    OC\Metadata\Provider\ExifProvider->execute(OC\Files\Node\File {})
 3. /var/www/html/lib/private/Metadata/FileEventListener.php line 101
    OC\Metadata\MetadataManager->generateMetadata(OC\Files\Node\File {}, "*** sensitive parameters replaced ***")
 4. /var/www/html/lib/private/EventDispatcher/ServiceEventListener.php line 87
    OC\Metadata\FileEventListener->handle(OCP\Files\Events\Node\NodeWrittenEvent {})
 5. /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php line 251
    OC\EventDispatcher\ServiceEventListener->__invoke(OCP\Files\Events\Node\NodeWrittenEvent {}, "OCP\\Files\\Eve ... t", Symfony\Componen ... {})
 6. /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php line 73
    Symfony\Component\EventDispatcher\EventDispatcher->callListeners([Closure {},Closure {}], "OCP\\Files\\Eve ... t", OCP\Files\Events\Node\NodeWrittenEvent {})
 7. /var/www/html/lib/private/EventDispatcher/EventDispatcher.php line 88
    Symfony\Component\EventDispatcher\EventDispatcher->dispatch(OCP\Files\Events\Node\NodeWrittenEvent {}, "OCP\\Files\\Eve ... t")
 8. /var/www/html/lib/private/EventDispatcher/EventDispatcher.php line 100
    OC\EventDispatcher\EventDispatcher->dispatch("OCP\\Files\\Eve ... t", OCP\Files\Events\Node\NodeWrittenEvent {})
 9. /var/www/html/lib/private/Files/Node/HookConnector.php line 118
    OC\EventDispatcher\EventDispatcher->dispatchTyped(OCP\Files\Events\Node\NodeWrittenEvent {})
10. /var/www/html/lib/private/legacy/OC_Hook.php line 106
    OC\Files\Node\HookConnector->postWrite(["/Nextcloud.png"])
11. /var/www/html/lib/private/Files/View.php line 641
    OC_Hook::emit("OC_Filesystem", "post_write", ["/Nextcloud.png"])
12. /var/www/html/lib/private/Files/View.php line 692
    OC\Files\View->emit_file_hooks_post(true, "/discord-634105 ... g")
13. /var/www/html/lib/private/Files/Node/File.php line 71
    OC\Files\View->file_put_contents("/discord-634105 ... g", null)
14. /var/www/html/lib/private/legacy/OC_Util.php line 257
    OC\Files\Node\File->putContent(null)
15. /var/www/html/lib/private/legacy/OC_Util.php line 216
    OC_Util::copyr("/var/www/html/core/skeleton", OC\Files\Node\Folder {})
16. /var/www/html/lib/private/User/Session.php line 553
    OC_Util::copySkeleton("*** sensitive parameters replaced ***", OC\Files\Node\Folder {})
17. /var/www/html/lib/private/User/Session.php line 403
    OC\User\Session->prepareUserLogin(true, "*** sensitive parameters replaced ***")
18. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 592
    OC\User\Session->completeLogin("*** sensitive parameters replaced ***")
19. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 448
    OCA\SocialLogin\Service\ProviderService->login("*** sensitive parameters replaced ***")
20. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 265
    OCA\SocialLogin\Service\ProviderService->auth("Hybridauth\\Provider\\Discord", ["https://nextcl ... "], "discord", "OAuth")
21. /var/www/html/custom_apps/sociallogin/lib/Controller/LoginController.php line 28
    OCA\SocialLogin\Service\ProviderService->handleDefault("discord")
22. /var/www/html/lib/private/AppFramework/Http/Dispatcher.php line 225
    OCA\SocialLogin\Controller\LoginController->oauth("discord")
23. /var/www/html/lib/private/AppFramework/Http/Dispatcher.php line 133
    OC\AppFramework\Http\Dispatcher->executeController(OCA\SocialLogin\ ... {}, "oauth")
24. /var/www/html/lib/private/AppFramework/App.php line 172
    OC\AppFramework\Http\Dispatcher->dispatch(OCA\SocialLogin\ ... {}, "oauth")
25. /var/www/html/lib/private/Route/Router.php line 298
    OC\AppFramework\App::main("OCA\\SocialLogi ... r", "oauth", OC\AppFramework\ ... {}, ["discord","sociallogin.login.oauth"])
26. /var/www/html/lib/base.php line 1047
    OC\Route\Router->match("/apps/sociallogin/oauth/discord")
27. /var/www/html/index.php line 36
    OC::handleRequest()

GET /apps/sociallogin/oauth/discord?code=wtJorNdskRDKFnZ2zmgRQN333Of9zj&state=HA-Z20DUGSMCWPVHL8OFEX1T54I6ANB9J3QY7KR
from 188.112.38.245 by discord-634105581567498952 at 2023-02-19T22:42:08+00:00

@kousu
Copy link
Author

kousu commented Feb 22, 2023

[PHP] Error: Error: exif_read_data(): File not supported at /var/www/html/lib/private/Metadata/Provider/ExifProvider.php#59 at <<closure>>

I get this one too, I think it's an unrelated problem. I think it's triggered by one of the skeleton files; NextCloud is trying to scan its metadata tags but failing:

{"reqId":"aJA5H5lcNck938xlgncC","level":3,"time":"2023-01-13T04:03:50+00:00","remoteAddr":"192.222.249.98","user":"admin","app":"PHP","method":"POST","url":"/index.php","message":"exif_read_data(): File not supported at /var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php#59","userAgent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0","version":"25.0.2.3","exception":{"Exception":"Error","Message":"exif_read_data(): File not supported at /var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php#59","Code":0,"Trace":[{"function":"onError","class":"OC\\Log\\ErrorHandler","type":"::"},{"file":"/var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php","line":59,"function":"exif_read_data"},{"file":"/var/www/nextcloud/lib/private/Metadata/MetadataManager.php","line":68,"function":"execute","class":"OC\\Metadata\\Provider\\ExifProvider","type":"->"},{"file":"/var/www/nextcloud/lib/private/Metadata/FileEventListener.php","line":101,"function":"generateMetadata","class":"OC\\Metadata\\MetadataManager","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/ServiceEventListener.php","line":87,"function":"handle","class":"OC\\Metadata\\FileEventListener","type":"->"},{"file":"/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":251,"function":"__invoke","class":"OC\\EventDispatcher\\ServiceEventListener","type":"->"},{"file":"/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":73,"function":"callListeners","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php","line":88,"function":"dispatch","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php","line":100,"function":"dispatch","class":"OC\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/Node/HookConnector.php","line":118,"function":"dispatchTyped","class":"OC\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Hook.php","line":106,"function":"postWrite","class":"OC\\Files\\Node\\HookConnector","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/View.php","line":641,"function":"emit","class":"OC_Hook","type":"::"},{"file":"/var/www/nextcloud/lib/private/Files/View.php","line":692,"function":"emit_file_hooks_post","class":"OC\\Files\\View","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/Node/File.php","line":71,"function":"file_put_contents","class":"OC\\Files\\View","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Util.php","line":257,"function":"putContent","class":"OC\\Files\\Node\\File","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Util.php","line":216,"function":"copyr","class":"OC_Util","type":"::"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":553,"function":"copySkeleton","class":"OC_Util","type":"::"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":403,"function":"prepareUserLogin","class":"OC\\User\\Session","type":"->"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":616,"function":"completeLogin","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":355,"function":"loginWithPassword","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/private/Setup.php","line":433,"function":"login","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/core/Controller/SetupController.php","line":69,"function":"install","class":"OC\\Setup","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/base.php","line":980,"function":"run","class":"OC\\Core\\Controller\\SetupController","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/index.php","line":36,"function":"handleRequest","class":"OC","type":"::"}],"File":"/var/www/nextcloud/lib/private/Log/ErrorHandler.php","Line":92,"CustomMessage":"--"}}

So

GET /apps/sociallogin/oauth/discord?code=wtJorNdskRDKFnZ2zmgRQN333Of9zj&state=HA-Z20DUGSMCWPVHL8OFEX1T54I6ANB9J3QY7KR
from 188.112.38.245 by discord-634105581567498952 at 2023-02-19T22:42:08+00:00

is the only interesting log, and it doesn't say much. 🤔


I was thinking about this and I realized that on mine I have enabled a bot user on my OAuth app, and I invited that bot user to my guild, with, well, probably too many permissions:

Screenshot_20230222_142002

But I tried removing it, and it still behaves itself for me

Screenshot_20230222_142132

So I don't think that's the issue.


What version of PHP are you on? I'm using 7.4 (old, I know, but it's what my distro happens to have at the moment).


You have been very helpful @pktiuk. I do not know what's wrong. I won't bother you any more if you just want to delete and reinstall the basic sociallogin app. I'll be sure to let you know if I make more progress though in the future.

@pktiuk
Copy link
Contributor

pktiuk commented Feb 22, 2023

I use docker from: https://github.com/nextcloud/all-in-one It has version: 8.0.26

@pktiuk
Copy link
Contributor

pktiuk commented Feb 28, 2023

I won't bother you any more if you just want to delete and reinstall the basic sociallogin app. I'll be sure to let you know if I make more progress though in the future.

I can still help you with this functionality. Helping you is in my best interest. I think this feature will be incredibly useful in my organization :)

@Thelvaen
Copy link

I am also really interested in mapping roles in a specific Discord guild directly to a group for a group I'm belonging to.

kousu added a commit to kousu/nextcloud-social-login that referenced this issue Aug 13, 2023
kousu added a commit to kousu/nextcloud-social-login that referenced this issue Aug 13, 2023
kousu added a commit to kousu/nextcloud-social-login that referenced this issue Aug 13, 2023
kousu added a commit to kousu/nextcloud-social-login that referenced this issue Aug 13, 2023
@pktiuk
Copy link
Contributor

pktiuk commented Nov 30, 2023

I think this issue can be closed now.
Reading roles in groups was implemented in eb1ab88 ❤️ 🎉

@zorn-v zorn-v closed this as completed Dec 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants