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

feat: add accept invitation endpoint #355

Merged
3 changes: 3 additions & 0 deletions apps/backend/config/sync/user-role.authenticated.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
{
"action": "plugin::upload.content-api.upload"
},
{
"action": "plugin::users-permissions.auth.acceptInvitation"
},
{
"action": "plugin::users-permissions.auth.changePassword"
},
Expand Down
3 changes: 3 additions & 0 deletions apps/backend/config/sync/user-role.contributor.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
{
"action": "plugin::upload.content-api.upload"
},
{
"action": "plugin::users-permissions.auth.acceptInvitation"
},
{
"action": "plugin::users-permissions.role.find"
},
Expand Down
29 changes: 29 additions & 0 deletions apps/backend/src/extensions/users-permissions/strapi-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = (plugin) => {
data: {
provider: "auth0",
password: null,
status: "invited",
},
});

Expand All @@ -74,5 +75,33 @@ module.exports = (plugin) => {
policies: [],
},
});

plugin.controllers.auth.acceptInvitation = async (ctx) => {
if (!ctx.state.user || !ctx.state.user.id) {
return (ctx.response.status = 401);
}

await strapi.query("plugin::users-permissions.user").update({
where: { id: ctx.state.user.id },
data: {
status: "active",
},
});

ctx.response.status = 200;
ctx.response.body = {
status: "success",
};
};

plugin.routes["content-api"].routes.unshift({
method: "PUT",
path: "/auth/accept-invitation",
handler: "auth.acceptInvitation",
config: {
prefix: "",
policies: [],
},
});
return plugin;
};
44 changes: 42 additions & 2 deletions apps/backend/tests/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const {
deleteUser,
getAllRoles,
getUserByRole,
getRoleId,
} = require("../helpers/helpers");

// user mock data
Expand All @@ -18,6 +19,14 @@ const mockUserData = {
blocked: null,
};

const invitedUserData = {
username: "invited",
email: "invited@user.com",
provider: "auth0",
confirmed: false,
status: "invited",
};

describe("auth", () => {
describe("invitation", () => {
let mockUser;
Expand All @@ -40,7 +49,7 @@ describe("auth", () => {
jest.clearAllMocks();
});

it("should set the user's provider to auth0 and delete the password", async () => {
it('should modify the user object into the "invited" state', async () => {
// There are subtle differences between what services.user.add and
// getUser return, so we use getUser for a fair comparison.
const user = await getUser(mockUserData.username);
Expand All @@ -52,11 +61,12 @@ describe("auth", () => {
expect(res.body).toEqual({ status: "success" });
expect(res.status).toEqual(200);
const updatedUser = await getUser(user.username);
expect(updatedUser).toEqual({
expect(updatedUser).toMatchObject({
...user,
provider: "auth0",
updatedAt: updatedUser.updatedAt,
password: null,
status: "invited",
});
});

Expand Down Expand Up @@ -126,4 +136,34 @@ describe("auth", () => {
}
});
});

describe("accept-invitation", () => {
afterEach(() => {
deleteUser(invitedUserData.username);
});

// TODO: loop over all roles after fetching them with getAllRoles
const roles = ["Editor", "Contributor"];

roles.forEach((role) => {
it(`should set a ${role} user as active if they are not already`, async () => {
const roleId = await getRoleId(role);
await strapi.plugins["users-permissions"].services.user.add({
...invitedUserData,
role: roleId,
});

const invitedUserToken = await getUserJWT(invitedUserData.username);

const res = await request(strapi.server.httpServer)
.put("/api/auth/accept-invitation")
.auth(invitedUserToken, { type: "bearer" });

expect(res.status).toEqual(200);
expect(res.body).toEqual({ status: "success" });
const updatedUser = await getUser(invitedUserData.username);
expect(updatedUser.status).toEqual("active");
});
});
});
});
Loading