rename/move according to zeitwerk

pull/8045/head
ulferts 5 years ago
parent b02c278667
commit cd049721d5
No known key found for this signature in database
GPG Key ID: A205708DE1284017
  1. 2
      app/controllers/journals_controller.rb
  2. 1
      app/controllers/wiki_controller.rb
  3. 57
      app/models/wiki_page.rb
  4. 70
      app/models/wikis/annotate.rb
  5. 39
      app/models/wikis/diff.rb
  6. 307
      lib/diff.rb
  7. 274
      modules/bcf/app/contracts/bcf/viewpoints/create_contract.rb
  8. 51
      modules/bcf/app/contracts/concerns/bcf/manage_bcf_guarded.rb
  9. 7
      modules/meeting/app/models/meeting_content.rb
  10. 26
      modules/two_factor_authentication/app/controllers/concerns/two_factor_authentication/backup_codes.rb
  11. 98
      modules/two_factor_authentication/app/controllers/concerns/two_factor_authentication/remember_token.rb
  12. 5
      modules/two_factor_authentication/app/controllers/two_factor_authentication/authentication_controller.rb
  13. 28
      modules/two_factor_authentication/app/controllers/two_factor_authentication/concerns/backup_codes.rb
  14. 100
      modules/two_factor_authentication/app/controllers/two_factor_authentication/concerns/remember_token.rb
  15. 2
      modules/two_factor_authentication/app/controllers/two_factor_authentication/my/remember_cookie_controller.rb
  16. 2
      modules/two_factor_authentication/app/controllers/two_factor_authentication/my/two_factor_devices_controller.rb
  17. 3
      modules/two_factor_authentication/app/controllers/two_factor_authentication/users/two_factor_devices_controller.rb

@ -27,8 +27,6 @@
# See docs/COPYRIGHT.rdoc for more details. # See docs/COPYRIGHT.rdoc for more details.
#++ #++
require 'diff'
class JournalsController < ApplicationController class JournalsController < ApplicationController
before_action :find_journal, except: [:index] before_action :find_journal, except: [:index]
before_action :find_optional_project, only: [:index] before_action :find_optional_project, only: [:index]

@ -28,7 +28,6 @@
# See docs/COPYRIGHT.rdoc for more details. # See docs/COPYRIGHT.rdoc for more details.
#++ #++
require 'diff'
require 'htmldiff' require 'htmldiff'
# The WikiController follows the Rails REST controller pattern but with # The WikiController follows the Rails REST controller pattern but with

@ -1,4 +1,5 @@
#-- encoding: UTF-8 #-- encoding: UTF-8
#-- copyright #-- copyright
# OpenProject is an open source project management software. # OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH # Copyright (C) 2012-2020 the OpenProject GmbH
@ -27,8 +28,6 @@
# See docs/COPYRIGHT.rdoc for more details. # See docs/COPYRIGHT.rdoc for more details.
#++ #++
require 'diff'
class WikiPage < ActiveRecord::Base class WikiPage < ActiveRecord::Base
belongs_to :wiki, touch: true belongs_to :wiki, touch: true
has_one :project, through: :wiki has_one :project, through: :wiki
@ -155,13 +154,13 @@ class WikiPage < ActiveRecord::Base
content_to = content.versions.find_by(version: version_to) content_to = content.versions.find_by(version: version_to)
content_from = content.versions.find_by(version: version_from) content_from = content.versions.find_by(version: version_from)
(content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil (content_to && content_from) ? Wikis::Diff.new(content_to, content_from) : nil
end end
def annotate(version = nil) def annotate(version = nil)
version = version ? version.to_i : content.version version = version ? version.to_i : content.version
c = content.versions.find_by(version: version) c = content.versions.find_by(version: version)
c ? WikiAnnotate.new(c) : nil c ? Wikis::Annotate.new(c) : nil
end end
def text def text
@ -257,53 +256,3 @@ class WikiPage < ActiveRecord::Base
errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id) errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
end end
end end
class WikiDiff < Redmine::Helpers::Diff
attr_reader :content_to, :content_from
def initialize(content_to, content_from)
@content_to = content_to
@content_from = content_from
super(content_to.data.text, content_from.data.text)
end
end
class WikiAnnotate
attr_reader :lines, :content
def initialize(content)
@content = content
current = content
current_lines = current.data.text.split(/\r?\n/)
@lines = current_lines.map { |t| [nil, nil, t] }
positions = []
current_lines.size.times do |i| positions << i end
while current.previous
d = current.previous.data.text.split(/\r?\n/).diff(current.data.text.split(/\r?\n/)).diffs.flatten
d.each_slice(3) do |s|
sign = s[0]
line = s[1]
if sign == '+' && positions[line] && positions[line] != -1
if @lines[positions[line]][0].nil?
@lines[positions[line]][0] = current.version
@lines[positions[line]][1] = current.data.author
end
end
end
d.each_slice(3) do |s|
sign = s[0]
line = s[1]
if sign == '-'
positions.insert(line, -1)
else
positions[line] = nil
end
end
positions.compact!
# Stop if every line is annotated
break unless @lines.detect { |line| line[0].nil? }
current = current.previous
end
@lines.each { |line| line[0] ||= current.version }
end
end

@ -0,0 +1,70 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
class Wikis::Annotate
attr_reader :lines, :content
def initialize(content)
@content = content
current = content
current_lines = current.data.text.split(/\r?\n/)
@lines = current_lines.map { |t| [nil, nil, t] }
positions = []
current_lines.size.times { |i| positions << i }
while current.previous
d = current.previous.data.text.split(/\r?\n/).diff(current.data.text.split(/\r?\n/)).diffs.flatten
d.each_slice(3) do |s|
sign = s[0]
line = s[1]
if sign == '+' && positions[line] && positions[line] != -1
if @lines[positions[line]][0].nil?
@lines[positions[line]][0] = current.version
@lines[positions[line]][1] = current.data.author
end
end
end
d.each_slice(3) do |s|
sign = s[0]
line = s[1]
if sign == '-'
positions.insert(line, -1)
else
positions[line] = nil
end
end
positions.compact!
# Stop if every line is annotated
break unless @lines.detect { |line| line[0].nil? }
current = current.previous
end
@lines.each { |line| line[0] ||= current.version }
end
end

@ -0,0 +1,39 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
class Wikis::Diff < Redmine::Helpers::Diff
attr_reader :content_to, :content_from
def initialize(content_to, content_from)
@content_to = content_to
@content_from = content_from
super(content_to.data.text, content_from.data.text)
end
end

@ -1,307 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
#-- encoding: UTF-8
module RedmineDiff
class Diff
VERSION = 0.3
def self.lcs(a, b)
astart = 0
bstart = 0
afinish = a.length - 1
bfinish = b.length - 1
mvector = []
# First we prune off any common elements at the beginning
while astart <= afinish && bstart <= afinish && a[astart] == b[bstart]
mvector[astart] = bstart
astart += 1
bstart += 1
end
# now the end
while astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish]
mvector[afinish] = bfinish
afinish -= 1
bfinish -= 1
end
bmatches = b.reverse_hash(bstart..bfinish)
thresh = []
links = []
(astart..afinish).each do |aindex|
aelem = a[aindex]
next unless bmatches.has_key? aelem
k = nil
bmatches[aelem].reverse_each { |bindex|
if k && (thresh[k] > bindex) && (thresh[k - 1] < bindex)
thresh[k] = bindex
else
k = thresh.replacenextlarger(bindex, k)
end
links[k] = [(k == 0) ? nil : links[k - 1], aindex, bindex] if k
}
end
if !thresh.empty?
link = links[thresh.length - 1]
while link
mvector[link[1]] = link[2]
link = link[0]
end
end
mvector
end
def makediff(a, b)
mvector = Diff.lcs(a, b)
ai = bi = 0
while ai < mvector.length
bline = mvector[ai]
if bline
while bi < bline
discardb(bi, b[bi])
bi += 1
end
match(ai, bi)
bi += 1
else
discarda(ai, a[ai])
end
ai += 1
end
while ai < a.length
discarda(ai, a[ai])
ai += 1
end
while bi < b.length
discardb(bi, b[bi])
bi += 1
end
match(ai, bi)
1
end
def compactdiffs
diffs = []
@diffs.each do |df|
i = 0
curdiff = []
while i < df.length
whot = df[i][0]
s = @isstring ? df[i][2].chr : [df[i][2]]
p = df[i][1]
last = df[i][1]
i += 1
while df[i] && df[i][0] == whot && df[i][1] == last + 1
s << df[i][2]
last = df[i][1]
i += 1
end
curdiff.push [whot, p, s]
end
diffs.push curdiff
end
diffs
end
attr_reader :diffs, :difftype
def initialize(diffs_or_a, b = nil, isstring = nil)
if b.nil?
@diffs = diffs_or_a
@isstring = isstring
else
@diffs = []
@curdiffs = []
makediff(diffs_or_a, b)
@difftype = diffs_or_a.class
end
end
def match(_ai, _bi)
@diffs.push @curdiffs unless @curdiffs.empty?
@curdiffs = []
end
def discarda(i, elem)
@curdiffs.push ['-', i, elem]
end
def discardb(i, elem)
@curdiffs.push ['+', i, elem]
end
def compact
Diff.new(compactdiffs)
end
def compact!
@diffs = compactdiffs
end
def inspect
@diffs.inspect
end
end
end
module Diffable
def diff(b)
RedmineDiff::Diff.new(self, b)
end
# Create a hash that maps elements of the array to arrays of indices
# where the elements are found.
def reverse_hash(range = (0...length))
revmap = {}
range.each do |i|
elem = self[i]
if revmap.has_key? elem
revmap[elem].push i
else
revmap[elem] = [i]
end
end
revmap
end
def replacenextlarger(value, high = nil)
high ||= length
if self.empty? || value > self[-1]
push value
return high
end
# binary search for replacement point
low = 0
while low < high
index = (high + low) / 2
found = self[index]
return nil if value == found
if value > found
low = index + 1
else
high = index
end
end
self[low] = value
# $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
# $stderr.puts self.inspect
# gets
# p length - low
low
end
def patch(diff)
newary = nil
if diff.difftype == String
newary = diff.difftype.new('')
else
newary = diff.difftype.new
end
ai = 0
bi = 0
diff.diffs.each do |d|
d.each { |mod|
case mod[0]
when '-'
while ai < mod[1]
newary << self[ai]
ai += 1
bi += 1
end
ai += 1
when '+'
while bi < mod[1]
newary << self[ai]
ai += 1
bi += 1
end
newary << mod[2]
bi += 1
else
raise 'Unknown diff action'
end
}
end
while ai < length
newary << self[ai]
ai += 1
bi += 1
end
newary
end
end
class Array
include Diffable
end
class String
include Diffable
end
# = Diff
# (({diff.rb})) - computes the differences between two arrays or
# strings. Copyright (C) 2001 Lars Christensen
#
# == Synopsis
#
# diff = Diff.new(a, b)
# b = a.patch(diff)
#
# == Class Diff
# === Class Methods
# --- Diff.new(a, b)
# --- a.diff(b)
# Creates a Diff object which represent the differences between
# ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
# of any objects, strings, or object of any class that include
# module ((|Diffable|))
#
# == Module Diffable
# The module ((|Diffable|)) is intended to be included in any class for
# which differences are to be computed. Diffable is included into String
# and Array when (({diff.rb})) is (({require}))'d.
#
# Classes including Diffable should implement (({[]})) to get element at
# integer indices, (({<<})) to append elements to the object and
# (({ClassName#new})) should accept 0 arguments to create a new empty
# object.
#
# === Instance Methods
# --- Diffable#patch(diff)
# Applies the differences from ((|diff|)) to the object ((|obj|))
# and return the result. ((|obj|)) is not changed. ((|obj|)) and
# can be either an array or a string, but must match the object
# from which the ((|diff|)) was created.

@ -0,0 +1,274 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module Bcf::Viewpoints
class CreateContract < ::ModelContract
include Bcf::ManageBcfGuarded
WHITELISTED_PROPERTIES = %w(guid
index
snapshot
orthogonal_camera
perspective_camera
clipping_planes
bitmaps
lines
components).freeze
ORTHOGONAL_CAMERA_PROPERTIES = %w(camera_view_point
camera_direction
camera_up_vector
view_to_world_scale).freeze
PERSPECTIVE_CAMERA_PROPERTIES = %w(camera_view_point
camera_direction
camera_up_vector
field_of_view).freeze
LINES_PROPERTIES = %w(start_point
end_point).freeze
CLIPPING_PLANES_PROPERTIES = %w(location
direction).freeze
COMPONENTS_PROPERTIES = %w(visibility
selection
coloring).freeze
COMPONENT_PROPERTIES = %w(ifc_guid
originating_system
authoring_tool_id).freeze
COLORING_PROPERTIES = %w(color
components).freeze
VISIBILITY_PROPERTIES = %w(default_visibility
exceptions
view_setup_hints).freeze
VIEW_SETUP_HINTS_PROPERTIES = %w(spaces_visible
space_boundaries_visible
openings_visible).freeze
COLOR_REGEXP = /#([0-9a-f]{2})?[0-9a-f]{6}/
WHITELISTED_DIMENSIONS = %w(x y z).freeze
attribute :uuid
attribute :issue
attribute :json_viewpoint do
validate_json_viewpoint_present
validate_json_viewpoint_hash
next if errors.any?
validate_properties
validate_snapshot
validate_index
validate_orthogonal_camera
validate_perspective_camera
validate_lines
validate_clipping_planes
validate_bitmaps
validate_components
validate_guid
end
def validate_json_viewpoint_present
errors.add(:json_viewpoint, :blank) unless viewpoint.present?
end
def validate_json_viewpoint_hash
errors.add(:json_viewpoint, :no_json) if viewpoint.present? && !viewpoint.is_a?(Hash)
end
def validate_properties
errors.add(:json_viewpoint, :unsupported_key) if viewpoint.present? && (viewpoint.keys - WHITELISTED_PROPERTIES).any?
end
def validate_snapshot
return unless (sjson = viewpoint['snapshot'])
errors.add(:json_viewpoint, :snapshot_type_unsupported) unless %w(jpg png).include? sjson['snapshot_type']
errors.add(:json_viewpoint, :snapshot_data_blank) unless sjson['snapshot_data'].present?
end
def validate_index
return unless (ijson = viewpoint['index'])
errors.add(:json_viewpoint, :index_not_integer) unless ijson.is_a? Integer
end
def validate_orthogonal_camera
return unless (ocjson = viewpoint['orthogonal_camera'])
if ocjson.keys != ORTHOGONAL_CAMERA_PROPERTIES ||
ocjson.except('view_to_world_scale').any? { |_, direction| invalid_direction?(direction) } ||
!ocjson['view_to_world_scale'].is_a?(Numeric)
errors.add(:json_viewpoint, :invalid_orthogonal_camera)
end
end
def validate_perspective_camera
return unless (pcjson = viewpoint['perspective_camera'])
if pcjson.keys != PERSPECTIVE_CAMERA_PROPERTIES ||
pcjson.except('field_of_view').any? { |_, direction| invalid_direction?(direction) } ||
!pcjson['field_of_view'].is_a?(Numeric)
errors.add(:json_viewpoint, :invalid_perspective_camera)
end
end
def validate_lines
return unless (ljson = viewpoint['lines'])
if !ljson.is_a?(Array) ||
ljson.any? { |line| invalid_line?(line) }
errors.add(:json_viewpoint, :invalid_lines)
end
end
def validate_clipping_planes
return unless (cpjson = viewpoint['clipping_planes'])
if !cpjson.is_a?(Array) ||
cpjson.any? { |cp| invalid_clipping_plane?(cp) }
errors.add(:json_viewpoint, :invalid_clipping_planes)
end
end
def validate_bitmaps
errors.add(:json_viewpoint, :bitmaps_not_writable) if viewpoint['bitmaps']
end
def validate_components
return unless (cjson = viewpoint['components'])
if !cjson.is_a?(Hash) ||
invalid_components_properties?(cjson)
errors.add(:json_viewpoint, :invalid_components)
end
end
def validate_guid
return unless (json_guid = viewpoint['guid'])
errors.add(:json_viewpoint, :mismatching_guid) if json_guid != model.uuid
end
def invalid_components_properties?(json)
(json.keys - COMPONENTS_PROPERTIES).any? ||
invalid_visibility?(json['visibility']) ||
invalid_components?(json['selection']) ||
invalid_colorings?(json['coloring'])
end
def invalid_line?(line)
invalid_hash_point?(line, LINES_PROPERTIES)
end
def invalid_clipping_plane?(line)
invalid_hash_point?(line, CLIPPING_PLANES_PROPERTIES)
end
def invalid_hash_point?(hash, whitelist)
!hash.is_a?(Hash) ||
hash.keys != whitelist ||
hash.values.any? { |v| invalid_point?(v) }
end
def invalid_visibility?(visibility)
visibility.nil? ||
!visibility.is_a?(Hash) ||
(visibility.keys - VISIBILITY_PROPERTIES).any? ||
invalid_default_visibility?(visibility['default_visibility']) ||
invalid_components?(visibility['exceptions']) ||
invalid_view_setup_hints?(visibility['view_setup_hints'])
end
def invalid_components?(components)
return false unless components.present?
!components.is_a?(Array) || components.any? { |component| invalid_component?(component) }
end
def invalid_colorings?(colorings)
return false unless colorings.present?
!colorings.is_a?(Array) || colorings.any? { |coloring| invalid_coloring?(coloring) }
end
def invalid_component?(component)
!component.is_a?(Hash) ||
component.empty? ||
(component.keys - COMPONENT_PROPERTIES).any? ||
component.values.any? { |v| !v.is_a?(String) }
end
def invalid_coloring?(coloring)
!coloring.is_a?(Hash) ||
coloring.keys != COLORING_PROPERTIES ||
invalid_color?(coloring['color']) ||
invalid_components?(coloring['components'])
end
def invalid_color?(color)
!(color.is_a?(String) && color.match?(COLOR_REGEXP))
end
def invalid_direction?(direction)
!direction.is_a?(Hash) ||
direction.keys != WHITELISTED_DIMENSIONS ||
direction.values.any? { |v| !v.is_a? Numeric }
end
alias_method :invalid_point?, :invalid_direction?
def invalid_default_visibility?(visibility)
visibility.present? &&
no_boolean?(visibility)
end
def invalid_view_setup_hints?(hints)
return false if hints.nil?
!hints.is_a?(Hash) ||
(hints.keys - VIEW_SETUP_HINTS_PROPERTIES).any? ||
hints.values.any? { |v| no_boolean?(v) }
end
def no_boolean?(property)
!(property.is_a?(TrueClass) || property.is_a?(FalseClass))
end
def viewpoint
model.json_viewpoint
end
end
end

@ -0,0 +1,51 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module Bcf
module ManageBcfGuarded
extend ActiveSupport::Concern
included do
def validate
validate_user_allowed_to_manage
super
end
private
def validate_user_allowed_to_manage
unless model.project && user.allowed_to?(:manage_bcf, model.project)
errors.add :base, :error_unauthorized
end
end
end
end
end

@ -27,11 +27,6 @@
#++ #++
# #
require_dependency 'wiki_page'
# Because of the WikiDiff class defined therein
require 'wiki_page'
class MeetingContent < ActiveRecord::Base class MeetingContent < ActiveRecord::Base
include OpenProject::Journal::AttachmentHelper include OpenProject::Journal::AttachmentHelper
@ -75,7 +70,7 @@ class MeetingContent < ActiveRecord::Base
content_to = journals.find_by_version(version_to) content_to = journals.find_by_version(version_to)
content_from = journals.find_by_version(version_from) content_from = journals.find_by_version(version_from)
(content_to && content_from) ? ::WikiDiff.new(content_to, content_from) : nil content_to && content_from ? Wikis::Diff.new(content_to, content_from) : nil
end end
def at_version(version) def at_version(version)

@ -0,0 +1,26 @@
module ::TwoFactorAuthentication
module BackupCodes
extend ActiveSupport::Concern
##
# Request user to enter backup code
def enter_backup_code
render
end
##
# Verify backup code
def verify_backup_code
code = params[:backup_code]
return fail_login(t('two_factor_authentication.error_invalid_backup_code')) unless code.present?
service = TwoFactorAuthentication::UseBackupCodeService.new user: @authenticated_user
result = service.verify code
if result.success?
complete_stage_redirect
else
fail_login(t('two_factor_authentication.error_invalid_backup_code'))
end
end
end
end

@ -0,0 +1,98 @@
module ::TwoFactorAuthentication
module RememberToken
extend ActiveSupport::Concern
included do
helper_method :has_valid_2fa_remember_token?
helper_method :remember_2fa_enabled?
helper_method :remember_2fa_days
end
##
# Check for valid 2FA autologin cookie and log in the user
# if that's the case
def perform_2fa_authentication_with_remember(service)
if has_valid_2fa_remember_token?(@authenticated_user)
complete_stage_redirect
else
perform_2fa_authentication service
end
end
##
# Set a 2FA autologin cookie for the user (if supported).
def set_remember_token!
return unless remember_2fa_enabled?
return unless params[:remember_me].present?
cookies.encrypted[remember_cookie_name] = {
value: new_token!(@authenticated_user),
httponly: true,
expires: remember_2fa_days.days.from_now,
secure: Setting.protocol == 'https'
}
end
##
# Remove the 2FA autologin cookie
# and all potentially stored tokens
def clear_remember_token!(user = current_user)
cookies.delete remember_cookie_name
::TwoFactorAuthentication::RememberedAuthToken
.where(user: user)
.delete_all
end
def remember_2fa_enabled?
remember_2fa_days > 0
end
##
# Return whether for the given user,
# any valid remember tokens exist (not necessary in this session!)
def any_remember_token_present?(user = current_user)
return false unless remember_2fa_enabled?
::TwoFactorAuthentication::RememberedAuthToken
.not_expired
.where(user: user)
.exists?
end
##
# Return whether the user has a valid remember token
# that is identified by his cookie value.
def has_valid_2fa_remember_token?(user = current_user)
return false unless remember_2fa_enabled?
token = get_2fa_remember_token(user)
token.present? && !token.expired?
end
##
# Try to read a Remember token from the cookie
def get_2fa_remember_token(user)
value = cookies.encrypted[remember_cookie_name]
return false unless value.present?
::TwoFactorAuthentication::RememberedAuthToken
.where(user: user)
.find_by_plaintext_value value
end
def remember_2fa_days
OpenProject::TwoFactorAuthentication::TokenStrategyManager.allow_remember_for_days
end
private
def remember_cookie_name
:op2fa_remember_token
end
def new_token!(user)
::TwoFactorAuthentication::RememberedAuthToken.create_and_return_value(user)
end
end
end

@ -1,10 +1,9 @@
module ::TwoFactorAuthentication module ::TwoFactorAuthentication
class AuthenticationController < ApplicationController class AuthenticationController < ApplicationController
# Remmeber token functionality # Remmeber token functionality
include ::TwoFactorAuthentication::Concerns::RememberToken include ::TwoFactorAuthentication::RememberToken
# Backup tokens functionality # Backup tokens functionality
include ::TwoFactorAuthentication::Concerns::BackupCodes include ::TwoFactorAuthentication::BackupCodes
# Include global layout helper # Include global layout helper
layout 'no_menu' layout 'no_menu'

@ -1,28 +0,0 @@
module ::TwoFactorAuthentication
module Concerns
module BackupCodes
extend ActiveSupport::Concern
##
# Request user to enter backup code
def enter_backup_code
render
end
##
# Verify backup code
def verify_backup_code
code = params[:backup_code]
return fail_login(t('two_factor_authentication.error_invalid_backup_code')) unless code.present?
service = TwoFactorAuthentication::UseBackupCodeService.new user: @authenticated_user
result = service.verify code
if result.success?
complete_stage_redirect
else
fail_login(t('two_factor_authentication.error_invalid_backup_code'))
end
end
end
end
end

@ -1,100 +0,0 @@
module ::TwoFactorAuthentication
module Concerns
module RememberToken
extend ActiveSupport::Concern
included do
helper_method :has_valid_2fa_remember_token?
helper_method :remember_2fa_enabled?
helper_method :remember_2fa_days
end
##
# Check for valid 2FA autologin cookie and log in the user
# if that's the case
def perform_2fa_authentication_with_remember(service)
if has_valid_2fa_remember_token?(@authenticated_user)
complete_stage_redirect
else
perform_2fa_authentication service
end
end
##
# Set a 2FA autologin cookie for the user (if supported).
def set_remember_token!
return unless remember_2fa_enabled?
return unless params[:remember_me].present?
cookies.encrypted[remember_cookie_name] = {
value: new_token!(@authenticated_user),
httponly: true,
expires: remember_2fa_days.days.from_now,
secure: Setting.protocol == 'https'
}
end
##
# Remove the 2FA autologin cookie
# and all potentially stored tokens
def clear_remember_token!(user = current_user)
cookies.delete remember_cookie_name
::TwoFactorAuthentication::RememberedAuthToken
.where(user: user)
.delete_all
end
def remember_2fa_enabled?
remember_2fa_days > 0
end
##
# Return whether for the given user,
# any valid remember tokens exist (not necessary in this session!)
def any_remember_token_present?(user = current_user)
return false unless remember_2fa_enabled?
::TwoFactorAuthentication::RememberedAuthToken
.not_expired
.where(user: user)
.exists?
end
##
# Return whether the user has a valid remember token
# that is identified by his cookie value.
def has_valid_2fa_remember_token?(user = current_user)
return false unless remember_2fa_enabled?
token = get_2fa_remember_token(user)
token.present? && !token.expired?
end
##
# Try to read a Remember token from the cookie
def get_2fa_remember_token(user)
value = cookies.encrypted[remember_cookie_name]
return false unless value.present?
::TwoFactorAuthentication::RememberedAuthToken
.where(user: user)
.find_by_plaintext_value value
end
def remember_2fa_days
OpenProject::TwoFactorAuthentication::TokenStrategyManager.allow_remember_for_days
end
private
def remember_cookie_name
:op2fa_remember_token
end
def new_token!(user)
::TwoFactorAuthentication::RememberedAuthToken.create_and_return_value(user)
end
end
end
end

@ -2,7 +2,7 @@ module ::TwoFactorAuthentication
module My module My
class RememberCookieController < ::ApplicationController class RememberCookieController < ::ApplicationController
# Remmeber token functionality # Remmeber token functionality
include ::TwoFactorAuthentication::Concerns::RememberToken include ::TwoFactorAuthentication::RememberToken
# Ensure user is logged in # Ensure user is logged in
before_action :require_login before_action :require_login

@ -9,7 +9,7 @@ module ::TwoFactorAuthentication
before_action :find_device, except: [:new, :index, :register] before_action :find_device, except: [:new, :index, :register]
# Remmeber token functionality # Remmeber token functionality
include ::TwoFactorAuthentication::Concerns::RememberToken include ::TwoFactorAuthentication::RememberToken
# Password confirmation helpers and actions # Password confirmation helpers and actions
include PasswordConfirmation include PasswordConfirmation

@ -15,8 +15,7 @@ module ::TwoFactorAuthentication
# Skip before action on delete_all # Skip before action on delete_all
skip_before_action :find_device, only: [:delete_all] skip_before_action :find_device, only: [:delete_all]
def index def index; end
end
## ##
# Register the device and let the user confirm # Register the device and let the user confirm

Loading…
Cancel
Save