<commit_before>jraphical = require 'jraphical'
Bongo     = require "bongo"

{secure, daisy, Base, signature} = Bongo

module.exports = class JInvitation extends jraphical.Module

  @trait __dirname, '../traits/grouprelated'
  @trait __dirname, '../traits/protected'

  fs       = require 'fs'
  crypto   = require 'crypto'
  nodePath = require 'path'
  createId = require 'hat'
  {uniq}   = require 'underscore'

  {permit} = require './group/permissionset'

  @isEnabledGlobally = yes

  {ObjectRef, dash, daisy, secure, signature} = require 'bongo'

  KodingError  = require '../error'
  JMail        = require './email'
  JGroup       = require './group'
  JPaymentPack = require './payment/pack'

  @share()

  @set
    permissions     :
      'send invitations'                  : ['moderator', 'admin']
    indexes         :
      code          : 'unique'
    sharedMethods   :

      instance:
        modifyMultiuse:
          (signature Object, Function)
        remove:
          (signature Function)

      static:
        inviteFriend:
          (signature Object, Function)
        create:
          (signature String, String, Object, Function)
        byCode:
          (signature String, Function)
        suggestCode: [
          (signature Function)
          (signature Object, Function)
          (signature Object, Function, Number)
        ]
        createMultiuse:
          (signature Object, Function)
#        createForResurrection:
#          (signature String, Function)
#        createMultiForResurrection:
#          (signature [String], Function)
#        byCodeForBeta:
#          (signature String, Function)

    sharedEvents    :
      static        : []
      instance      : []
    schema          :
      code          :
        type        : String
        required    : yes
      email         : String
      username      : String
      group         :
        type        : String
        required    : yes
      customMessage :
        subject     : String
        body        : String
      uses          :
        type        : Number
        default     : 0
      maxUses       :
        type        : Number
        default     : 1
      type          :
        type        : String
        enum        : ['invalid invitation type', ['friend','admin','multiuse']]
        default     : 'admin'
      status        :
        type        : String
        enum        : ['invalid status type', [
          'sent','active','blocked','redeemed','couldnt send email','accepted','ignored'
        ]]
        default     : 'active'
      origin        : ObjectRef
      memo          : String
      createdAt     :
        type        : Date
        default     : -> new Date
    relationships   :
      invitedBy     :
        targetType  : 'JAccount'
        as          : 'inviter'
      redeemer      :
        targetType  : 'JAccount'
        as          : 'redeemer'

  remove$: permit 'send invitations',
    success: (client, callback=->)-> @remove callback

  @byCode = (code, callback)-> @one {code}, callback

  @byCodeForBeta = (code, callback)->
    @one {code, group:"resurrection"}, callback

  @generateInvitationCode = (type, email, group)->
    code = crypto.createHmac 'sha1', 'kodingsecret'
    code.update type
    code.update email
    code.update group  if group
    code.digest 'hex'

  @getHostAndProtocol = do->
    {host, protocol} = require('../config').email
    protocol = if host is 'localhost' then 'http:' else 'https:'
    protocol ?= protocol.split(':').shift()+':'
    return {host, protocol}

  redeem: secure ({connection:{delegate}}, callback=->)->
    operation = $inc: uses: 1

    if @type is 'multiuse'
      isRedeemed = @uses + 1 >= @maxUses
    else
      isRedeemed = yes
    operation.$set = status: 'redeemed'  if isRedeemed

    JGroup.one slug: @group, (err, group) =>
      callback err  if err
      group.fetchSubscription (err, subscription) =>
        callback err  if err
        JPaymentPack.one tags: "user", (err, pack) =>
          callback err  if err
          subscription.debit pack, (err) =>
            callback err  if err
            @update operation, (err) =>
              return callback err  if err
              @addRedeemer delegate, callback

  # send invites from group dashboard
  @create = secure (client, group, email, options, callback)->
    [callback, options] = [options, callback]  unless callback<commit_msg>Groups: pack is sent as an object<commit_after>jraphical = require 'jraphical'
Bongo     = require "bongo"

{secure, daisy, Base, signature} = Bongo

module.exports = class JInvitation extends jraphical.Module

  @trait __dirname, '../traits/grouprelated'
  @trait __dirname, '../traits/protected'

  fs       = require 'fs'
  crypto   = require 'crypto'
  nodePath = require 'path'
  createId = require 'hat'
  {uniq}   = require 'underscore'

  {permit} = require './group/permissionset'

  @isEnabledGlobally = yes

  {ObjectRef, dash, daisy, secure, signature} = require 'bongo'

  KodingError  = require '../error'
  JMail        = require './email'
  JGroup       = require './group'
  JPaymentPack = require './payment/pack'

  @share()

  @set
    permissions     :
      'send invitations'                  : ['moderator', 'admin']
    indexes         :
      code          : 'unique'
    sharedMethods   :

      instance:
        modifyMultiuse:
          (signature Object, Function)
        remove:
          (signature Function)

      static:
        inviteFriend:
          (signature Object, Function)
        create:
          (signature String, String, Object, Function)
        byCode:
          (signature String, Function)
        suggestCode: [
          (signature Function)
          (signature Object, Function)
          (signature Object, Function, Number)
        ]
        createMultiuse:
          (signature Object, Function)
#        createForResurrection:
#          (signature String, Function)
#        createMultiForResurrection:
#          (signature [String], Function)
#        byCodeForBeta:
#          (signature String, Function)

    sharedEvents    :
      static        : []
      instance      : []
    schema          :
      code          :
        type        : String
        required    : yes
      email         : String
      username      : String
      group         :
        type        : String
        required    : yes
      customMessage :
        subject     : String
        body        : String
      uses          :
        type        : Number
        default     : 0
      maxUses       :
        type        : Number
        default     : 1
      type          :
        type        : String
        enum        : ['invalid invitation type', ['friend','admin','multiuse']]
        default     : 'admin'
      status        :
        type        : String
        enum        : ['invalid status type', [
          'sent','active','blocked','redeemed','couldnt send email','accepted','ignored'
        ]]
        default     : 'active'
      origin        : ObjectRef
      memo          : String
      createdAt     :
        type        : Date
        default     : -> new Date
    relationships   :
      invitedBy     :
        targetType  : 'JAccount'
        as          : 'inviter'
      redeemer      :
        targetType  : 'JAccount'
        as          : 'redeemer'

  remove$: permit 'send invitations',
    success: (client, callback=->)-> @remove callback

  @byCode = (code, callback)-> @one {code}, callback

  @byCodeForBeta = (code, callback)->
    @one {code, group:"resurrection"}, callback

  @generateInvitationCode = (type, email, group)->
    code = crypto.createHmac 'sha1', 'kodingsecret'
    code.update type
    code.update email
    code.update group  if group
    code.digest 'hex'

  @getHostAndProtocol = do->
    {host, protocol} = require('../config').email
    protocol = if host is 'localhost' then 'http:' else 'https:'
    protocol ?= protocol.split(':').shift()+':'
    return {host, protocol}

  redeem: secure ({connection:{delegate}}, callback=->)->
    operation = $inc: uses: 1

    if @type is 'multiuse'
      isRedeemed = @uses + 1 >= @maxUses
    else
      isRedeemed = yes
    operation.$set = status: 'redeemed'  if isRedeemed

    JGroup.one slug: @group, (err, group) =>
      return callback err  if err
      group.fetchSubscription (err, subscription) =>
        return callback err  if err
        JPaymentPack.one tags: "user", (err, pack) =>
          return callback err  if err
          subscription.debit {pack}, (err) =>
            return callback err  if err
            @update operation, (err) =>
              return callback err  if err
              @addRedeemer delegate, callback

  # send invites from group dashboard
  @create = secure (client, group, email, options, callback)->
    [callback, options] = [options, callback]  unless callback
{'fraction_non_alphanumeric': 0.10531628532974428, 'fraction_numerical': 0.0011215791834903544, 'mean_word_length': 1.7979290869155946, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6641159', 'n_tokens_mistral': 2471, 'n_tokens_neox': 2400, 'n_words': 691}