JakyeRU / Larascord

Larascord is a package that allows you to authenticate users in your Laravel application using Discord.
https://larascord.jakye.me
MIT License
65 stars 13 forks source link

[FEATURE] Allow Login per Guild Role #37

Closed thephilluk closed 1 year ago

thephilluk commented 2 years ago

Is your feature request related to a problem? Please describe. I am currently building a Bugtracker for our Gaming community. we only wan't people with a certain role to be able to login to the Site

Describe the solution you'd like a way to add a Key-Value pair for guild-role permissions

JakyeRU commented 2 years ago

Hello @thephilluk ,

I've been thinking about adding this feature for a while now but besides the normal OAuth2 you're gonna have to also configure a Bearer token to log into a Discord bot which is in the Guild to check a user's roles.

I'll see what I can do.

thephilluk commented 2 years ago

Hey @JakyeRU , Thanks for your quick response. Maybe we can take this one step further and make certain areas of the site only accessible to people with certain roles. So some kind of way to either:

thephilluk commented 2 years ago

Hey @JakyeRU , any update on this?

JakyeRU commented 2 years ago

Hello @thephilluk, Right now I don't have the necessary free time to work on this feature, and I'm sorry about that.

I can assure you that it has all the chances to get implemented. I was thinking of creating a Discord bot (hosted by me for those who don't want to host it and open source for those who want to host it themselves) and a simple API with Express that'll communicate with the Laravel application.

jnijland commented 2 years ago

Hello @thephilluk, Right now I don't have the necessary free time to work on this feature, and I'm sorry about that.

I can assure you that it has all the chances to get implemented. I was thinking of creating a Discord bot (hosted by me for those who don't want to host it and open source for those who want to host it themselves) and a simple API with Express that'll communicate with the Laravel application.

Love this idea @JakyeRU 👍

JakyeRU commented 1 year ago

I've abandoned the idea of creating a Discord bot with an express API since I can hit Discord's API directly using the bot's access token.

The next issue is that I can't hit Discord's API every time a request is made to check Users' roles because that will reach Discord's rate limit pretty fast. This approach might work for smaller applications, but for medium to large-scale applications won't. A possible solution to this problem is a system that allows a User to sync their roles in a Guild(s) every 5-10 minutes.

Any other suggestions are welcomed.

SrPeterr commented 1 year ago

I think that the best solution is the one you mentioned, 5-10min to sync, and the first time they login and save to the DB if possible

JakyeRU commented 1 year ago

Discord added an "Interactions Endpoint URL" which allows the package to receive interactions through HTTP rather than a bot user. This solves the roles sync issue.

image

I'll have to play with it a bit and develop this feature.

JakyeRU commented 1 year ago

Apparently, the "Interactions Endpoint URL" I mentioned earlier can only be used to receive interactions (e.g. slash commands), not events. (e.g. role added) Creating a slash command in the Discord server to allow users to update their roles on the website should do the job.

JakyeRU commented 1 year ago

I've implemented a prototype in #44. It is still a work in progress and testing is needed.

If anyone is interested in testing it, here are the steps:

After Larascord is installed, open config/larascord.php, enable guild_roles_enabled on line 130, and provide a guild and some roles for testing.

Example:

'guild_roles_enabled' => true,
'guild_roles' => [
    '684887322342705462' => ['1046373443903438851', '996138916581212261']
],

Warning This feature makes one request to the Discord API for each guild you specify. (Because you need to fetch the roles for each guild). At the moment the database is not checked for roles when the user logs in. It will always fetch the roles from the Discord API. The roles are only updated in the database when the user logs in. The roles from the database can be used in a middleware. I'm working on a better way to do this, but for now, this should work.

SrPeterr commented 1 year ago

Hi! When running migrations I'm getting this error:

SQLSTATE[42000]: Syntax error or access violation: 1101 BLOB, TEXT, GEOMETRY or JSON column 'roles' can't have a default value (Connection: mysql, SQL: alter table `users` add `roles` json not null default '{}')

Also, activating in the config and adding the roles, when I try to log in I get this: { "larascord_message": "Couldn't get the servers you're in.", "message": "HTTP request returned status code 429:\n{\"global\": false, \"message\": \"You are being rate limited.\", \"retry_after\": 0.965}\n", "code": 429 }

EDIT: I waited and when I try to log-in I get this error: (removed) should be ids, just removed them for security


"message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'roles' in 'field list' (Connection: mysql, SQL: update `users` set `roles` = {\"(removed)\":[\"(removed)\"]}, `users`.`updated_at` = 2023-04-14 19:36:06 where `id` = (removed))",
"code": "42S22"```
JakyeRU commented 1 year ago

Thank you @SrPeterr for giving it a try.

Seems like the issue is that the 2023_04_06_101123_add_roles_to_users_table.php migration did not run properly.

I tested the migration on my MariaDB server. Are you using a MySQL server?

I've encountered similar problems before with a MariaDB server and a MySQL Community Server. The MariaDB server executed the query without any problems, but the MySQL Community Server gave an error message saying "Integrity constraint violation".

SrPeterr commented 1 year ago

No problem, happy to help @JakyeRU

Yeah, Im using MySQL server, to be more precise: v8.1.11

JakyeRU commented 1 year ago

I have removed the default value for the column roles. It should allow you to run the migration now.

SrPeterr commented 1 year ago

Working perfect now, just got some questions about how does guild_roles work

'guild_roles' => [
    '684887322342705462' => ['1046373443903438851', '996138916581212261']
],

First ID is the guild ID and the others ID are roles ID?

JakyeRU commented 1 year ago

Yes, the first one is the ID of the guild, and then the ID(s) of the role(s).

JakyeRU commented 1 year ago

In the next update, the bot and its access token will no longer be used to get the user's role.

By requesting the OAuth2 permission guilds.members.read and hitting the endpoint https://discord.com/api/users/@me/guilds/USER_ID/member you are able to get the roles for each guild without requiring the bot to be in each of them.

Discord seems to show this permission as Read your member info (nickname, avatar, roles, etc...) for servers you belong to. image

JakyeRU commented 1 year ago

I should have checked if Discord had this functionality first before complicating things with a bot.