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: reset password statements for pocketbase plugin #137

Merged
merged 5 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 53 additions & 7 deletions pkg/pocketbase/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,46 @@ export const authWithPassword = p.new(['my_credentials'], 'login', async (ctx) =
}
});

/**
* @internal
*/
export const requestPasswordReset = p.new(['email'], 'ask password reset', async (ctx) => {
const email = ctx.fetch('email') as string;
if (!(await isPbRunning())) return ctx.fail('Client is not running');

try {
const res = await pb.collection('users').requestPasswordReset(email);
return ctx.pass({res});
} catch (err) {
return ctx.fail(new PocketBaseError(err.message));
}
});

// At the moment this statement is not used
// and there is not a simple way to test it
// thus it is commented out
/*
const confirmPassswordResetParametersSchema = z.object({
token: z.string(),
newPassword: z.string().min(8).max(73),
newPasswordConfirm: z.string().min(8).max(73),
});
export type ConfirmPassswordResetParameters = z.infer<typeof confirmPassswordResetParametersSchema>;
export const confirmPassswordReset = p.new(['reset_parameters'], 'confirm password reset', async (ctx) => {
const p = ctx.fetch('reset_parameters') as ConfirmPassswordResetParameters;

const validation = confirmPassswordResetParametersSchema.safeParse(p);
if (!validation.success) return ctx.fail(validation.error);
if (!(await isPbRunning())) return ctx.fail('Client is not running');
try {
const res = await pb.collection('users').confirmPasswordReset(p.token, p.newPassword, p.newPasswordConfirm);
return ctx.pass(res);
} catch (err) {
return ctx.fail(new PocketBaseError(err.message));
}
});
*/

/**
* @internal
*/
Expand Down Expand Up @@ -276,9 +316,12 @@ export const deleteRecord = p.new(['delete_parameters'], 'delete record', async
if (!validation.success) return ctx.fail(new PocketBaseError(validation.error.message));

const { collection, id } = p;
const res = await pb.collection(collection).delete(id);
if (res) return ctx.pass('deleted');
return ctx.fail(new PocketBaseError('shit happened'));
try {
await pb.collection(collection).delete(id);
return ctx.pass('deleted');
} catch (err) {
return ctx.fail(new PocketBaseError(err.message));
}
});

const sendParametersSchema = z.object({
Expand All @@ -303,10 +346,13 @@ export const sendRequest = p.new(['url','send_parameters'], 'send request', asyn
const validateUrl = urlSchema.safeParse(u);
if (!validateUrl.success) return ctx.fail(new PocketBaseError(validateUrl.error.message));

// @ts-expect-error - Somehow, "send" requires properties that are not
const res = await pb.send(u, p);
if (res) return ctx.pass(res);
return ctx.fail(new PocketBaseError('shit happened'));
try {
// @ts-expect-error - Somehow, "send" requires properties that are not
const res = await pb.send(u, p);
return ctx.pass(res);
} catch(err) {
return ctx.fail(new PocketBaseError(err.message));
}
})

export const pocketbase = p;
Expand Down
37 changes: 37 additions & 0 deletions pkg/pocketbase/test/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,40 @@ test('should make a request', async (t) => {
t.is(res.result['output']["message"], `Hello ${param}`);
});

test('should create a user then ask for password reset', async (t) => {
const script = `
Rule unknown ignore
Given I connect to 'pb_address' and start pb client
Given I send create_parameters 'create_parameters' and send record_parameters 'record_parameters' and create record
Given I send email 'my_email' and ask password reset and output into 'output'
Given I have a 'string dictionary' named 'output'
Then print data
`;
const slangroom = new Slangroom(pocketbase);

const email = `${randomString()}@test.eu`;

const data = {
pb_address,
create_parameters: {
collection: 'users',
record: {
email,
password,
passwordConfirm: password,
name: email
},
},
record_parameters: {
requestKey: "testPasswordReset",
},
my_email: email,
};

const res = await slangroom.execute(script, {
data,
});
// @ts-expect-error - Don't know the shape of the object in advance
t.truthy(res?.result?.['output']?.res);

})
37 changes: 37 additions & 0 deletions pkg/pocketbase/test/pb_migrations/1716277118_updated_users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <reference path="../pb_data/types.d.ts" />
migrate((db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("_pb_users_auth_")

collection.createRule = ""
collection.options = {
"allowEmailAuth": true,
"allowOAuth2Auth": true,
"allowUsernameAuth": true,
"exceptEmailDomains": null,
"manageRule": null,
"minPasswordLength": 8,
"onlyEmailDomains": null,
"requireEmail": true
}

return dao.saveCollection(collection)
}, (db) => {
const dao = new Dao(db)
const collection = dao.findCollectionByNameOrId("_pb_users_auth_")

collection.createRule = null
collection.options = {
"allowEmailAuth": true,
"allowOAuth2Auth": true,
"allowUsernameAuth": true,
"exceptEmailDomains": null,
"manageRule": null,
"minPasswordLength": 8,
"onlyEmailDomains": null,
"onlyVerified": false,
"requireEmail": true
}

return dao.saveCollection(collection)
})
Loading