mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-04-14 11:46:23 +00:00
Grant subscription to every user during registration and make first user an admin.
This commit is contained in:
parent
2242a46b31
commit
799ff58903
5 changed files with 11 additions and 65 deletions
|
|
@ -12,6 +12,7 @@ The following noteworthy changes were applied to the Habitica source code:
|
||||||
|
|
||||||
- Dockerfile and Github Workflow to create the production containers for hosting
|
- Dockerfile and Github Workflow to create the production containers for hosting
|
||||||
- every user automatically gets a subscription on registration that never needs to be renewed
|
- every user automatically gets a subscription on registration that never needs to be renewed
|
||||||
|
- first registered used automatically gets admin rights
|
||||||
- locations for buying gems with money were replaced with options to buy with gold (e.g., the quick access in the header)
|
- locations for buying gems with money were replaced with options to buy with gold (e.g., the quick access in the header)
|
||||||
- group plans can be created without payment
|
- group plans can be created without payment
|
||||||
- emails are sent directly via a configured SMTP server instead of using the Mailchimp (Mandrill) web-service
|
- emails are sent directly via a configured SMTP server instead of using the Mailchimp (Mandrill) web-service
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,14 @@ async function registerLocal (req, res, { isV3 = false }) {
|
||||||
passwordHashMethod: 'bcrypt',
|
passwordHashMethod: 'bcrypt',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'purchased.plan': {
|
||||||
|
planId: 'basic',
|
||||||
|
customerId: 'habitrpg',
|
||||||
|
dateCreated: new Date(),
|
||||||
|
dateUpdated: new Date(),
|
||||||
|
gemsBought: 0,
|
||||||
|
},
|
||||||
|
'permissions.fullAccess': ! await User.findOne().exec(), // admin access for the first registered user
|
||||||
preferences: {
|
preferences: {
|
||||||
language: req.language,
|
language: req.language,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import { paymentConstants } from './constants';
|
||||||
import { cancelSubscription, createSubscription } from './subscriptions'; // eslint-disable-line import/no-cycle
|
import { cancelSubscription, createSubscription } from './subscriptions'; // eslint-disable-line import/no-cycle
|
||||||
|
|
||||||
const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL');
|
const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL');
|
||||||
const JOINED_GROUP_PLAN = 'joined group plan';
|
|
||||||
|
|
||||||
function _dateDiff (earlyDate, lateDate) {
|
function _dateDiff (earlyDate, lateDate) {
|
||||||
if (!earlyDate || !lateDate || moment(lateDate).isBefore(earlyDate)) return 0;
|
if (!earlyDate || !lateDate || moment(lateDate).isBefore(earlyDate)) return 0;
|
||||||
|
|
@ -61,7 +60,6 @@ async function addSubToGroupUser (member, group) {
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS = 'iOS_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS = 'iOS_subscription';
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GROUP_PLAN = 'group_plan_free_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GROUP_PLAN = 'group_plan_free_subscription';
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_LIFETIME_FREE = 'lifetime_free_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_LIFETIME_FREE = 'lifetime_free_subscription';
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL = 'normal_subscription';
|
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_UNKNOWN = 'unknown_type_of_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_UNKNOWN = 'unknown_type_of_subscription';
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
|
||||||
|
|
||||||
|
|
@ -153,11 +151,6 @@ async function addSubToGroupUser (member, group) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member.hasNotCancelled()) {
|
|
||||||
await member.cancelSubscription({ cancellationReason: JOINED_GROUP_PLAN });
|
|
||||||
previousSubscriptionType = EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
plan = member.purchased.plan.toObject();
|
plan = member.purchased.plan.toObject();
|
||||||
let extraMonths = Number(plan.extraMonths);
|
let extraMonths = Number(plan.extraMonths);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import { paymentConstants } from './constants';
|
||||||
import { addSubscriptionToGroupUsers, cancelGroupUsersSubscription } from './groupPayments'; // eslint-disable-line import/no-cycle
|
import { addSubscriptionToGroupUsers, cancelGroupUsersSubscription } from './groupPayments'; // eslint-disable-line import/no-cycle
|
||||||
|
|
||||||
// @TODO: Abstract to shared/constant
|
// @TODO: Abstract to shared/constant
|
||||||
const JOINED_GROUP_PLAN = 'joined group plan';
|
|
||||||
const analytics = getAnalyticsServiceByEnvironment();
|
const analytics = getAnalyticsServiceByEnvironment();
|
||||||
|
|
||||||
function _findMysteryItems (user, dateMoment) {
|
function _findMysteryItems (user, dateMoment) {
|
||||||
|
|
@ -424,12 +423,7 @@ async function cancelSubscription (data) {
|
||||||
|
|
||||||
await cancelGroupUsersSubscription(group);
|
await cancelGroupUsersSubscription(group);
|
||||||
} else {
|
} else {
|
||||||
// cancelling a user subscription
|
return;
|
||||||
plan = data.user.purchased.plan;
|
|
||||||
emailType = 'cancel-subscription';
|
|
||||||
// When cancelling because the user joined a group plan, no cancel-subscription email is sent
|
|
||||||
// because the group-member-join email says the subscription is cancelled.
|
|
||||||
if (data.cancellationReason && data.cancellationReason === JOINED_GROUP_PLAN) sendEmail = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plan.customerId === paymentConstants.GROUP_PLAN_CUSTOMER_ID) {
|
if (plan.customerId === paymentConstants.GROUP_PLAN_CUSTOMER_ID) {
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,7 @@ import {
|
||||||
|
|
||||||
import { model as UserNotification } from '../userNotification';
|
import { model as UserNotification } from '../userNotification';
|
||||||
import schema from './schema'; // eslint-disable-line import/no-cycle
|
import schema from './schema'; // eslint-disable-line import/no-cycle
|
||||||
import payments from '../../libs/payments/payments'; // eslint-disable-line import/no-cycle
|
|
||||||
import * as inboxLib from '../../libs/inbox'; // eslint-disable-line import/no-cycle
|
import * as inboxLib from '../../libs/inbox'; // eslint-disable-line import/no-cycle
|
||||||
import amazonPayments from '../../libs/payments/amazon'; // eslint-disable-line import/no-cycle
|
|
||||||
import stripePayments from '../../libs/payments/stripe'; // eslint-disable-line import/no-cycle
|
|
||||||
import paypalPayments from '../../libs/payments/paypal'; // eslint-disable-line import/no-cycle
|
|
||||||
import { model as NewsPost } from '../newsPost';
|
import { model as NewsPost } from '../newsPost';
|
||||||
import { TransactionModel as Transaction } from '../transaction';
|
import { TransactionModel as Transaction } from '../transaction';
|
||||||
|
|
||||||
|
|
@ -325,42 +321,6 @@ schema.statics.addComputedStatsToJSONObj = function addComputedStatsToUserJSONOb
|
||||||
return userStatsJSON;
|
return userStatsJSON;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels a subscription.
|
|
||||||
*
|
|
||||||
* @param options
|
|
||||||
* @param options.user The user object who is purchasing
|
|
||||||
* @param options.groupId The id of the group purchasing a subscription
|
|
||||||
* @param options.headers The request headers (only for Amazon subscriptions)
|
|
||||||
* @param options.cancellationReason A text string to control sending an email
|
|
||||||
*
|
|
||||||
* @return a Promise from api.cancelSubscription()
|
|
||||||
*/
|
|
||||||
// @TODO: There is currently a three way relation between the user,
|
|
||||||
// payment methods and the payment helper
|
|
||||||
// This creates some odd Dependency Injection issues. To counter that,
|
|
||||||
// we use the user as the third layer
|
|
||||||
// To negotiate between the payment providers and the payment helper
|
|
||||||
// (which probably has too many responsibilities)
|
|
||||||
// In summary, currently is is best practice to use this method to cancel a user subscription,
|
|
||||||
// rather than calling the
|
|
||||||
// payment helper.
|
|
||||||
schema.methods.cancelSubscription = async function cancelSubscription (options = {}) {
|
|
||||||
const { plan } = this.purchased;
|
|
||||||
|
|
||||||
options.user = this;
|
|
||||||
if (plan.paymentMethod === amazonPayments.constants.PAYMENT_METHOD) {
|
|
||||||
return amazonPayments.cancelSubscription(options);
|
|
||||||
} if (plan.paymentMethod === stripePayments.constants.PAYMENT_METHOD) {
|
|
||||||
return stripePayments.cancelSubscription(options);
|
|
||||||
} if (plan.paymentMethod === paypalPayments.constants.PAYMENT_METHOD) {
|
|
||||||
return paypalPayments.subscribeCancel(options);
|
|
||||||
}
|
|
||||||
// Android and iOS subscriptions cannot be cancelled by Habitica.
|
|
||||||
|
|
||||||
return payments.cancelSubscription(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
schema.methods.getUtcOffset = function getUtcOffset () {
|
schema.methods.getUtcOffset = function getUtcOffset () {
|
||||||
return common.fns.getUtcOffset(this);
|
return common.fns.getUtcOffset(this);
|
||||||
};
|
};
|
||||||
|
|
@ -489,17 +449,7 @@ async function getUserGroupData (user) {
|
||||||
// User is allowed to buy gems if no group has `leaderOnly.getGems` === true or if
|
// User is allowed to buy gems if no group has `leaderOnly.getGems` === true or if
|
||||||
// its the group leader
|
// its the group leader
|
||||||
schema.methods.canGetGems = async function canObtainGems () {
|
schema.methods.canGetGems = async function canObtainGems () {
|
||||||
const user = this;
|
return true;
|
||||||
const { plan } = user.purchased;
|
|
||||||
|
|
||||||
if (!user.isSubscribed() || plan.customerId !== payments.constants.GROUP_PLAN_CUSTOMER_ID) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const groups = await getUserGroupData(user);
|
|
||||||
|
|
||||||
return groups
|
|
||||||
.every(g => !g.hasActiveGroupPlan() || g.leader === user._id || g.leaderOnly.getGems !== true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
schema.methods.isMemberOfGroupPlan = async function isMemberOfGroupPlan () {
|
schema.methods.isMemberOfGroupPlan = async function isMemberOfGroupPlan () {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue