Unverified Commit ed63dd05 authored by sym's avatar sym Committed by GitHub
Browse files

Merge pull request #31 from yzx9/feature/sharelatex411

Update sharelatex to v4.1.1:
- v.4.1.1 works but i have still troubles migrating the projects from 3.3.2 (even after running the migrations scripts from 3.5.10)
parents ba1e78f2 062f17e0
Loading
Loading
Loading
Loading
+156 −149
Original line number Diff line number Diff line
version: '2.2'
version: "2.2"
services:
  sharelatex:
    restart: always
@@ -36,7 +36,7 @@ services:
      # SHARELATEX_EMAIL_AWS_SES_SECRET_KEY:
      SHARELATEX_EMAIL_SMTP_HOST: smtp.${MYDOMAIN}
      SHARELATEX_EMAIL_SMTP_PORT: 587
            SHARELATEX_EMAIL_SMTP_SECURE: 'false'
      SHARELATEX_EMAIL_SMTP_SECURE: "false"
      # SHARELATEX_EMAIL_SMTP_USER:
      # SHARELATEX_EMAIL_SMTP_PASS:
      # SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true
@@ -48,11 +48,11 @@ services:
      # https://github.com/overleaf/overleaf/issues/628
      # https://github.com/overleaf/web/issues/367
      # Fixed in 2.0.2 (Release date: 2019-11-26)
            SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' 
            SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true'
      SHARELATEX_ALLOW_PUBLIC_ACCESS: "true"
      SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: "true"

            SHARELATEX_SECURE_COOKIE: 'true'
            SHARELATEX_BEHIND_PROXY: 'true'
      SHARELATEX_SECURE_COOKIE: "true"
      SHARELATEX_BEHIND_PROXY: "true"

      LDAP_SERVER: ldaps://LDAPSERVER:636
      LDAP_BASE: ou=people,dc=DOMAIN,dc=TLD
@@ -68,18 +68,18 @@ services:
      # LDAP_BIND_PW:

      # Only allow users matching LDAP_USER_FILTER
            LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
      LDAP_USER_FILTER: "(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"

      # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true.
      # Admin Users can invite external (non ldap) users. This feature makes only sense
      # when ALLOW_EMAIL_LOGIN is set to 'true'. Additionally admins can send
      # system wide messages.
            LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
            ALLOW_EMAIL_LOGIN: 'true'
      LDAP_ADMIN_GROUP_FILTER: "(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"
      ALLOW_EMAIL_LOGIN: "true"

      # All users in the LDAP_CONTACT_FILTER are loaded from the ldap server into contacts.
            LDAP_CONTACT_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
            LDAP_CONTACTS: 'false'
      LDAP_CONTACT_FILTER: "(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"
      LDAP_CONTACTS: "false"

      # Same property, unfortunately with different names in
      # different locations
@@ -87,16 +87,16 @@ services:
      REDIS_HOST: redis
      REDIS_PORT: 6379

            ENABLED_LINKED_FILE_TYPES: 'url,project_file'
      ENABLED_LINKED_FILE_TYPES: "url,project_file"

      # Enables Thumbnail generation using ImageMagick
            ENABLE_CONVERSIONS: 'true'
      ENABLE_CONVERSIONS: "true"

  mongo:
    restart: always
        image: mongo
    image: mongo:4.4
    container_name: mongo
        ports:
    expose:
      - 27017
    volumes:
      - ${MYDATA}/mongo_data:/data/db
@@ -105,20 +105,30 @@ services:
      interval: 10s
      timeout: 10s
      retries: 5
    command: "--replSet overleaf"

  # See also: https://github.com/overleaf/overleaf/issues/1120
  mongoinit:
    image: mongo:4.4
    # this container will exit after executing the command
    restart: "no"
    depends_on:
      mongo:
        condition: service_healthy
    entrypoint:
      [
        "mongo",
        "--host",
        "mongo:27017",
        "--eval",
        'rs.initiate({ _id: "overleaf", members: [ { _id: 0, host: "mongo:27017" } ] })',
      ]

  redis:
    restart: always
        image: redis:5.0.0
    image: redis:6.2
    container_name: redis
        # modify to get rid of the redis issue #35 and #19 with a better solution
        # WARNING: /proc/sys/net/core/somaxconn is set to the lower value of 128.
        # for vm overcommit: enable first on host system 
        # sysctl vm.overcommit_memory=1 (and add it to rc.local)
        # then you do not need it in the redis container
        sysctls:
            - net.core.somaxconn=65535
            # - vm.overcommit_memory=1
        ports:
    expose:
      - 6379
    volumes:
      - ${MYDATA}/redis_data:/data
@@ -128,7 +138,6 @@ services:
      timeout: 5s
      retries: 5


  simple-certbot:
    restart: always
    image: certbot/certbot
@@ -146,5 +155,3 @@ services:
        trap exit TERM;\
        certbot certonly --standalone -d ${MYDOMAIN} --agree-tos -m ${MYMAIL} -n ; \
        while :; do certbot renew; sleep 240h & wait $${!}; done;

+237 −221
Original line number Diff line number Diff line
version: '2.2'
version: "2.2"
services:
  traefik:
    image: traefik:latest
@@ -20,7 +20,6 @@ services:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/dynamic_conf.yml:/dynamic_conf.yml
      - ./traefik/users.htpasswd:/users.htpasswd

    command:
      - "--api=true"
      - "--api.dashboard=true"
@@ -118,7 +117,7 @@ services:
      SHARELATEX_EMAIL_FROM_ADDRESS: "noreply@${MYDOMAIN}"
      SHARELATEX_EMAIL_SMTP_HOST: smtp.${MYDOMAIN}
      SHARELATEX_EMAIL_SMTP_PORT: 587
            SHARELATEX_EMAIL_SMTP_SECURE: 'false'
      SHARELATEX_EMAIL_SMTP_SECURE: "false"
      # SHARELATEX_EMAIL_SMTP_USER:
      # SHARELATEX_EMAIL_SMTP_PASS:
      # SHARELATEX_EMAIL_SMTP_TLS_REJECT_UNAUTH: true
@@ -130,11 +129,11 @@ services:
      # https://github.com/overleaf/overleaf/issues/628
      # https://github.com/overleaf/web/issues/367
      # Fixed in 2.0.2 (Release date: 2019-11-26)
            SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' 
            SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: 'true'
      SHARELATEX_ALLOW_PUBLIC_ACCESS: "true"
      SHARELATEX_ALLOW_ANONYMOUS_READ_AND_WRITE_SHARING: "true"

            SHARELATEX_SECURE_COOKIE: 'true'
            SHARELATEX_BEHIND_PROXY: 'true'
      SHARELATEX_SECURE_COOKIE: "true"
      SHARELATEX_BEHIND_PROXY: "true"

      LDAP_SERVER: ldaps://LDAPSERVER:636
      LDAP_BASE: ou=people,dc=DOMAIN,dc=TLD
@@ -150,18 +149,18 @@ services:
      # LDAP_BIND_PW:

      # Only allow users matching LDAP_USER_FILTER
            LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
      LDAP_USER_FILTER: "(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"

      # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true.
      # Admin Users can invite external (non ldap) users. This feature makes only sense
      # when ALLOW_EMAIL_LOGIN is set to 'true'. Additionally admins can send
      # system wide messages.
            LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
            ALLOW_EMAIL_LOGIN: 'true'
      LDAP_ADMIN_GROUP_FILTER: "(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"
      ALLOW_EMAIL_LOGIN: "true"

      # All users in the LDAP_CONTACT_FILTER are loaded from the ldap server into contacts.
            LDAP_CONTACT_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)'
            LDAP_CONTACTS: 'false'
      LDAP_CONTACT_FILTER: "(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)"
      LDAP_CONTACTS: "false"

      # Same property, unfortunately with different names in
      # different locations
@@ -169,14 +168,14 @@ services:
      REDIS_HOST: redis
      REDIS_PORT: 6379

            ENABLED_LINKED_FILE_TYPES: 'url,project_file'
      ENABLED_LINKED_FILE_TYPES: "url,project_file"

      # Enables Thumbnail generation using ImageMagick
            ENABLE_CONVERSIONS: 'true'
      ENABLE_CONVERSIONS: "true"

  mongo:
    restart: always
        image: mongo
    image: mongo:4.4
    container_name: mongo
    expose:
      - 27017
@@ -195,10 +194,28 @@ services:
      - "traefik.tcp.routers.mongodb.entrypoints=mongo"
    networks:
      - web
    command: "--replSet overleaf"

  # See also: https://github.com/overleaf/overleaf/issues/1120
  mongoinit:
    image: mongo:4.4
    # this container will exit after executing the command
    restart: "no"
    depends_on:
      mongo:
        condition: service_healthy
    entrypoint:
      [
        "mongo",
        "--host",
        "mongo:27017",
        "--eval",
        'rs.initiate({ _id: "overleaf", members: [ { _id: 0, host: "mongo:27017" } ] })',
      ]

  redis:
    restart: always
        image: redis:5.0.0
    image: redis:6.2
    container_name: redis
    # modify to get rid of the redis issue #35 and #19 with a better solution
    # WARNING: /proc/sys/net/core/somaxconn is set to the lower value of 128.
@@ -223,4 +240,3 @@ services:
networks:
  web:
    external: true
+2 −2
Original line number Diff line number Diff line
FROM sharelatex/sharelatex:3.3.2
FROM sharelatex/sharelatex:4.1.1
# FROM sharelatex/sharelatex:latest
# latest might not be tested 
# e.g. the AuthenticationManager.js script had to be adapted after versions 2.3.1 
@@ -45,7 +45,7 @@ RUN npm install -g npm && \
    sed -iE "s/email@example.com/${login_text:-user}/g" /overleaf/services/web/app/views/user/login.pug && \
    ## Collaboration settings display (share project placeholder) | edit line 146
    ## share.pug file was removed in later versions
    sed -iE "s%placeholder=.*$%placeholder=\"${collab_text}\"%g" /overleaf/services/web/app/views/project/editor/share.pug && \
    # sed -iE "s%placeholder=.*$%placeholder=\"${collab_text}\"%g" /overleaf/services/web/app/views/project/editor/share.pug && \
    ## extend pdflatex with option shell-esacpe ( fix for closed overleaf/overleaf/issues/217 and overleaf/docker-image/issues/45 )
    ## do this in different ways for different sharelatex versions
    sed -iE "s%-synctex=1\",%-synctex=1\", \"-shell-escape\",%g" /overleaf/services/clsi/app/js/LatexRunner.js && \
+525 −182

File changed.

Preview size limit exceeded, changes collapsed.

+118 −127
Original line number Diff line number Diff line
/* eslint-disable
    camelcase,
    max-len,
    no-unused-vars,
/**
 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 * Modified from 906765c
 * <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 */
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
 * decaffeinate suggestions:
 * DS101: Remove unnecessary use of Array.from
 * DS102: Remove unnecessary code created because of implicit returns
 * DS207: Consider shorter variations of null checks
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */
let ContactsController
const AuthenticationController = require('../Authentication/AuthenticationController')

const SessionManager = require('../Authentication/SessionManager')
const ContactManager = require('./ContactManager')
const UserGetter = require('../User/UserGetter')
const logger = require('@overleaf/logger')
const Modules = require('../../infrastructure/Modules')
const { Client } = require('ldapts');

module.exports = ContactsController = {
  getContacts(req, res, next) {
    const user_id = SessionManager.getLoggedInUserId(req.session)
    return ContactManager.getContactIds(
      user_id,
      { limit: 50 },
      function (error, contact_ids) {
        if (error != null) {
          return next(error)
const { expressify } = require('../../util/promises')

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
const { Client } = require('ldapts')
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

function _formatContact(contact) {
  return {
    id: contact._id?.toString(),
    email: contact.email || '',
    first_name: contact.first_name || '',
    last_name: contact.last_name || '',
    type: 'user',
  }
}
        return UserGetter.getUsers(
          contact_ids,
          {

async function getContacts(req, res) {
  const userId = SessionManager.getLoggedInUserId(req.session)

  const contactIds = await ContactManager.promises.getContactIds(userId, {
    limit: 50,
  })

  let contacts = await UserGetter.promises.getUsers(contactIds, {
    email: 1,
    first_name: 1,
    last_name: 1,
    holdingAccount: 1,
          },
          function (error, contacts) {
            if (error != null) {
              return next(error)
            }
  })

  // UserGetter.getUsers may not preserve order so put them back in order
  const positions = {}
            for (let i = 0; i < contact_ids.length; i++) {
              const contact_id = contact_ids[i]
  for (let i = 0; i < contactIds.length; i++) {
    const contact_id = contactIds[i]
    positions[contact_id] = i
  }
  contacts.sort(
              (a, b) =>
                positions[a._id != null ? a._id.toString() : undefined] -
                positions[b._id != null ? b._id.toString() : undefined]
    (a, b) => positions[a._id?.toString()] - positions[b._id?.toString()]
  )

  // Don't count holding accounts to discourage users from repeating mistakes (mistyped or wrong emails, etc)
            contacts = contacts.filter(c => !c.holdingAccount)
	    ContactsController.getLdapContacts(contacts).then((ldapcontacts) => { 
  contacts = contacts.filter((c) => !c.holdingAccount)

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  const ldapcontacts = getLdapContacts(contacts)
  contacts.push(ldapcontacts)
              contacts = contacts.map(ContactsController._formatContact)
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

           return Modules.hooks.fire('getContacts', user_id, contacts, function(
              error,
              additional_contacts
            ) {
              if (error != null) {
                return next(error)
              }
              contacts = contacts.concat(...Array.from(additional_contacts || []))
              return res.send({
                contacts
              })
            })
  	  }).catch(e => console.log("Error appending ldap contacts" + e))
  contacts = contacts.map(_formatContact)

        }
  const additionalContacts = await Modules.promises.hooks.fire(
    'getContacts',
    userId,
    contacts
  )

  contacts = contacts.concat(...(additionalContacts || []))
  return res.json({
    contacts,
  })
  },
  async getLdapContacts(contacts) {
    if (process.env.LDAP_CONTACTS === undefined || !(process.env.LDAP_CONTACTS.toLowerCase() === 'true')) {
}

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
async function getLdapContacts(contacts) {
  if (
    process.env.LDAP_CONTACTS === undefined ||
    !(process.env.LDAP_CONTACTS.toLowerCase() === 'true')
  ) {
    return contacts
  }
  const client = new Client({
    url: process.env.LDAP_SERVER,
    });
  })

  // if we need a ldap user try to bind
  if (process.env.LDAP_BIND_USER) {
    try {
        await client.bind(process.env.LDAP_BIND_USER, process.env.LDAP_BIND_PW);
      await client.bind(process.env.LDAP_BIND_USER, process.env.LDAP_BIND_PW)
    } catch (ex) {
        console.log("Could not bind LDAP reader user: " + String(ex) )
      console.log('Could not bind LDAP reader user: ' + String(ex))
    }
  }

@@ -101,39 +95,36 @@ module.exports = ContactsController = {
  // get user data
  try {
    // if you need an client.bind do it here.
      const {searchEntries,searchReferences,} = await client.search(ldap_base, {scope: 'sub',filter: process.env.LDAP_CONTACT_FILTER ,});
      await searchEntries;
    const { searchEntries, searchReferences } = await client.search(ldap_base, {
      scope: 'sub',
      filter: process.env.LDAP_CONTACT_FILTER,
    })
    await searchEntries
    for (var i = 0; i < searchEntries.length; i++) {
      var entry = new Map()
       var obj = searchEntries[i];
      var obj = searchEntries[i]
      entry['_id'] = undefined
      entry['email'] = obj['mail']
      entry['first_name'] = obj['givenName']
      entry['last_name'] = obj['sn']
       entry['type'] = "user"
      entry['type'] = 'user'
      // Only add to contacts if entry is not there.
      if (contacts.indexOf(entry) === -1) {
          contacts.push(entry);
        contacts.push(entry)
      }
    }
  } catch (ex) {
    console.log(String(ex))
    }  
  } finally {
    // console.log(JSON.stringify(contacts))
    finally {
    // even if we did not use bind - the constructor of
    // new Client() opens a socket to the ldap server
    client.unbind()
    return contacts
  }
  },
  _formatContact(contact) {
    return {
      id: contact._id != null ? contact._id.toString() : undefined,
      email: contact.email || '',
      first_name: contact.first_name || '',
      last_name: contact.last_name || '',
      type: 'user',
}
  },
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

module.exports = {
  getContacts: expressify(getContacts),
}