ezframe 0.0.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +1 -1
  4. data/asset/css/materialize.min.css +13 -0
  5. data/asset/css/style.css +3 -0
  6. data/asset/html/index.html +1 -0
  7. data/{app_template/asset/image/favicon.ico → asset/image/c_e.ico} +0 -0
  8. data/asset/js/ezframe.js +387 -0
  9. data/exe/check_column_yml +64 -0
  10. data/exe/console +2 -2
  11. data/exe/{create_table.rb → create_table} +7 -4
  12. data/exe/dbmigrate +174 -0
  13. data/exe/html2ruby +61 -0
  14. data/ezframe.gemspec +10 -8
  15. data/lib/ezframe.rb +9 -3
  16. data/lib/ezframe/auth.rb +50 -31
  17. data/lib/ezframe/column_set.rb +314 -103
  18. data/lib/ezframe/column_type.rb +456 -99
  19. data/lib/ezframe/config.rb +27 -6
  20. data/lib/ezframe/controller.rb +41 -38
  21. data/lib/ezframe/database.rb +171 -52
  22. data/lib/ezframe/editor_common.rb +74 -0
  23. data/lib/ezframe/email.rb +34 -0
  24. data/lib/ezframe/ezlog.rb +40 -0
  25. data/lib/ezframe/ht.rb +42 -17
  26. data/lib/ezframe/html.rb +47 -31
  27. data/lib/ezframe/japanese_utils.rb +15 -0
  28. data/lib/ezframe/jquery-ui.rb +29 -0
  29. data/lib/ezframe/loader.rb +4 -4
  30. data/lib/ezframe/main_editor.rb +19 -0
  31. data/lib/ezframe/main_page_kit.rb +226 -0
  32. data/lib/ezframe/materialize.rb +10 -14
  33. data/lib/ezframe/message.rb +46 -0
  34. data/lib/ezframe/page_base.rb +59 -71
  35. data/lib/ezframe/route.rb +126 -0
  36. data/lib/ezframe/server.rb +16 -5
  37. data/lib/ezframe/single_page_editor.rb +22 -0
  38. data/lib/ezframe/single_page_kit.rb +199 -0
  39. data/lib/ezframe/sub_editor.rb +25 -0
  40. data/lib/ezframe/sub_page_kit.rb +213 -0
  41. data/lib/ezframe/template.rb +5 -4
  42. data/lib/ezframe/util.rb +45 -23
  43. data/lib/ezframe/version.rb +1 -1
  44. metadata +74 -34
  45. data/.rubocop.yml +0 -44
  46. data/app_template/asset/js/ezframe.js +0 -288
  47. data/app_template/config.ru +0 -10
  48. data/app_template/config/generic.yml +0 -3
  49. data/app_template/config/materialize.yml +0 -5
  50. data/app_template/pages/basic.rb +0 -5
  51. data/exe/setup.rb +0 -15
  52. data/lib/ezframe/editor.rb +0 -188
  53. data/lib/ezframe/model.rb +0 -52
  54. data/lib/ezframe/page_kit.rb +0 -63
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ #codnig: utf-8
3
+
4
+ =begin
5
+
6
+ column/*.ymlのチェックをする。
7
+
8
+ =end
9
+ require "ezframe"
10
+
11
+ # https://stackoverflow.com/questions/4911105/in-ruby-how-to-be-warned-of-duplicate-keys-in-hashes-when-loading-a-yaml-docume
12
+ def duplicate_keys(file_or_content)
13
+ yaml = file_or_content.is_a?(File) ? file_or_content.read : file_or_content
14
+ duplicate_keys = []
15
+
16
+ validator = ->(node, parent_path) do
17
+ if node.is_a?(Psych::Nodes::Mapping)
18
+ children = node.children.each_slice(2) # In a Mapping, every other child is the key node, the other is the value node.
19
+ duplicates = children.map { |key_node, _value_node| key_node }.group_by(&:value).select { |_value, nodes| nodes.size > 1 }
20
+
21
+ duplicates.each do |key, nodes|
22
+ duplicate_key = {
23
+ file: (file_or_content.path if file_or_content.is_a?(File)),
24
+ key: parent_path + [key],
25
+ occurrences: nodes.map { |occurrence| "line: #{occurrence.start_line + 1}" },
26
+ }.compact
27
+
28
+ duplicate_keys << duplicate_key
29
+ end
30
+
31
+ children.each { |key_node, value_node| validator.call(value_node, parent_path + [key_node ? key_node.value : nil].compact) }
32
+ else
33
+ node.children.to_a.each { |child| validator.call(child, parent_path) }
34
+ end
35
+ end
36
+
37
+ ast = Psych.parse_stream(yaml)
38
+ validator.call(ast, [])
39
+
40
+ duplicate_keys
41
+ end
42
+
43
+ Ezframe::Config.init
44
+ Dir["column/*.yml"].each do |file|
45
+ instr = File.read(file)
46
+ dup = duplicate_keys(instr)
47
+ if dup && dup.length > 0
48
+ puts "#{file}\n#{dup}"
49
+ end
50
+ yaml = YAML.load(File.open(file), symbolize_names: true)
51
+ upper = Object.const_get("Ezframe")
52
+ yaml.each do |column|
53
+ type = column["type"]
54
+ unless type
55
+ puts "#{file}: type is not defined: key=#{column['key']}"
56
+ next
57
+ end
58
+ klass = "Ezframe::#{type.to_camel}Type"
59
+ unless upper.const_defined?(klass)
60
+ puts "#{file}: unknown type: key=#{column['key']}, type=#{type}"
61
+ end
62
+ end
63
+ end
64
+
@@ -10,5 +10,5 @@ require "ezframe"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
14
- IRB.start(__FILE__)
13
+ require "pry"
14
+ Pry.start(__FILE__)
@@ -6,7 +6,10 @@ $:.push("lib")
6
6
  require 'ezframe'
7
7
  require 'sequel'
8
8
 
9
- Ezframe::Config.load_files("config")
10
- Ezframe::Model.init
11
- model = Ezframe::Model.get_clone
12
- model.create_tables
9
+ include Ezframe
10
+
11
+ Config.init
12
+ DB.init
13
+ ColumnSets.init
14
+
15
+ ColumnSets.create_tables
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env ruby
2
+ #coding: utf-8
3
+ require "ezframe"
4
+ include Ezframe
5
+
6
+ module Ezframe
7
+ module Model
8
+ class DBInfo
9
+ def initialize
10
+ @db_columns = {}
11
+ @db_typ = get_database_type(Config[:database])
12
+ case @db_typ
13
+ when "postgresql"
14
+ get_info_from_postgres
15
+ when "sqlite"
16
+ get_info_from_sqlite
17
+ else
18
+ raise "unknown database system"
19
+ end
20
+ end
21
+
22
+ def get_db_info(table_name)
23
+ return @db_columns[table_name.to_sym]
24
+ end
25
+
26
+ def get_info_from_postgres
27
+ sql = "SELECT * FROM information_schema.columns"
28
+ begin
29
+ data_a = DB.sequel[sql].all
30
+ rescue => e
31
+ EzLog.error("get_info_from_postgres: #{e}")
32
+ return nil
33
+ end
34
+ data_a.each do |row|
35
+ table_name, col_name = row[:table_name], row[:column_name]
36
+ next if col_name.nil? || table_name.nil?
37
+ next unless ColumnSets.refer(table_name)
38
+ @db_columns[table_name.to_sym] ||= {}
39
+ @db_columns[table_name.to_sym][col_name.to_sym] = normalize_dbtype(row[:data_type])
40
+ end
41
+ end
42
+
43
+ def get_info_from_sqlite
44
+ sql = "SELECT * from sqlite_master;"
45
+ data_a = DB.sequel[sql].all
46
+ return nil unless data_a
47
+ data_a.each do |data|
48
+ sql = data[:sql]
49
+ parse_create_sql(sql)
50
+ end
51
+ end
52
+
53
+ def parse_create_sql(sql)
54
+ # EzLog.debug("parse_create_sql: #{sql}")
55
+ if sql =~ /CREATE TABLE \`(\w+)\` \(/i
56
+ table_name = $1
57
+ else
58
+ return
59
+ end
60
+ @db_columns[table_name.to_sym] ||= {}
61
+ column_a = sql.split(", ")
62
+ column_a.each do |line|
63
+ if line =~ /\`(\w+)\`\s(\w+)/
64
+ colkey, dbtype = $1, $2
65
+ @db_columns[table_name.to_sym][colkey.to_sym] = dbtype
66
+ end
67
+ end
68
+ end
69
+
70
+ def get_database_type(config)
71
+ return config.split("://")[0]
72
+ end
73
+
74
+ def exec_sql(sql)
75
+ begin
76
+ DB.sequel.run(sql)
77
+ rescue => e
78
+ EzLog.error("dbmigrate: exec_sql: #{e}")
79
+ end
80
+ end
81
+
82
+ def normalize_dbtype(dbtype)
83
+ return nil unless dbtype
84
+ return "int" if dbtype == "integer"
85
+ return "timestamp" if dbtype.index("timestamp")
86
+ return dbtype
87
+ end
88
+
89
+ def set_default(column)
90
+ default_value = column.attribute[:default]
91
+ if default_value
92
+ unless %w[int].include?(column.db_type)
93
+ default_value = "'#{default_value}'"
94
+ end
95
+ exec_sql("ALTER TABLE #{column.parent.name} ALTER #{column.key} SET DEFAULT #{default_value}")
96
+ end
97
+ end
98
+
99
+ def check_diff(column_set)
100
+ table_name = column_set.name
101
+ dbcols = get_db_info(table_name)
102
+ unless dbcols
103
+ ColumnSets.create_one_table(table_name, ColumnSets.get(table_name.to_sym))
104
+ return
105
+ end
106
+ column_set.each do |column|
107
+ next if %w[id updated_at created_at deleted_at].include?(column.key.to_s)
108
+ dbtype = dbcols[column.key]
109
+ new_type = column.db_type
110
+ if !new_type || new_type.empty?
111
+ EzLog.error("check_diff: no db_type: table=#{table_name}:key=#{column.key}")
112
+ next
113
+ end
114
+ unless dbtype
115
+ exec_sql("ALTER TABLE #{table_name} ADD #{column.key} #{new_type};")
116
+ set_default(column)
117
+ next
118
+ end
119
+ if dbtype != new_type
120
+ exec_sql("ALTER TABLE #{table_name} ALTER COLUMN #{column.key} DROP DEFAULT;")
121
+ unless change_type(table, column.key, new_type)
122
+ # 失敗したときは名前を変更してカラム追加
123
+ rename_column(table_name, column.key, "#{column.key}_bak")
124
+ add_column(table, column.key, new_type)
125
+ end
126
+ set_default(column)
127
+ end
128
+ end
129
+ end
130
+
131
+ # カラム追加
132
+ def add_column(table_name, key, typ)
133
+ begin
134
+ exec_sql("ALTER TABLE #{table_name} ADD #{key} #{typ};")
135
+ rescue => e
136
+ EzLog.error("change_type: error: #{e.class}:#{e}:#{e.backtrace}")
137
+ return nil
138
+ end
139
+ return true
140
+ end
141
+
142
+ # カラムの型変更
143
+ def change_type(table_name, key, typ)
144
+ begin
145
+ exec_sql("ALTER TABLE #{table_name} ALTER #{key} TYPE #{typ};")
146
+ rescue => e
147
+ EzLog.error("change_type: error: #{e.class}:#{e}:#{e.backtrace}")
148
+ return nil
149
+ end
150
+ return true
151
+ end
152
+
153
+ # カラムの名前変更
154
+ def rename_column(table_name, old_key, new_key)
155
+ begin
156
+ exec_sql("ALTER TABLE #{table_name} RENAME #{old_key} TO #{new_key};")
157
+ rescue => e
158
+ EzLog.error("rename_column: error: #{e.class}:#{e}:#{e.backtrace}")
159
+ return nil
160
+ end
161
+ return true
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ Config.init
168
+ DB.init
169
+ ColumnSets.init
170
+ dbinfo = Model::DBInfo.new
171
+
172
+ ColumnSets.each do |table_name, column_set|
173
+ dbinfo.check_diff(column_set)
174
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ #coding: utf-8
3
+ =begin
4
+
5
+ HTMLから、hthash生成するrubyプログラムを生成する
6
+
7
+ =end
8
+ require "nokogiri"
9
+
10
+ class Html2Ruby
11
+ def show_leaves(node, depth=0)
12
+ res = []
13
+ indent = " "*depth
14
+ node.children.each do |child|
15
+ next if child.name == "comment"
16
+ if child.name == "text"
17
+ if child.content.strip.empty?
18
+ next
19
+ else
20
+ res.push "#{indent}\"#{child.content}\""
21
+ end
22
+ else
23
+ attrs = child.attributes.map do |k, v|
24
+ if k.index("-")
25
+ key_s = "\"#{k}\""
26
+ else
27
+ key_s = k
28
+ if k == "class"
29
+ if v =~/\s/
30
+ cls_a = v.split(/\s+/)
31
+ v = "%w[#{cls_a.join(' ')}]"
32
+ end
33
+ end
34
+ end
35
+ "#{key_s}: \"#{v}\""
36
+ end
37
+ descendant = show_leaves(child, depth+1)
38
+ if descendant && descendant.strip.length > 10
39
+ attrs.push("child: \n#{descendant}\n")
40
+ res.push "#{indent}Ht.#{child.name}(#{attrs.join(', ')}#{indent})"
41
+ else
42
+ res.push "#{indent}Ht.#{child.name}(#{attrs.join(', ')})"
43
+ end
44
+ end
45
+ end
46
+ if res.length > 1
47
+ res_s = res.join(",\n")
48
+ return "[ #{res_s} ]"
49
+ else
50
+ return res[0]
51
+ end
52
+ end
53
+
54
+ def show_all(file)
55
+ doc = Nokogiri::HTML(File.open(file))
56
+ puts show_leaves(doc.root)
57
+ end
58
+ end
59
+
60
+ node = Html2Ruby.new
61
+ node.show_all(ARGV[0])
@@ -30,13 +30,15 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.add_development_dependency "bundler", "~> 1.16"
34
- spec.add_development_dependency "minitest", '~> 5.13.0'
35
- spec.add_development_dependency "nokogiri", '~> 1.10.7'
36
- spec.add_development_dependency "rack-test", '~> 1.1.0'
33
+ spec.add_development_dependency "bundler", '>= 1.16'
34
+ spec.add_development_dependency "minitest", '>= 5.13.0'
35
+ spec.add_development_dependency "nokogiri", '>= 1.10.7'
36
+ spec.add_development_dependency "rack-test", '>= 1.1.0'
37
+ spec.add_development_dependency "pry", '>= 0.12.2'
37
38
 
38
- spec.add_runtime_dependency "rake", "~> 13.0"
39
- spec.add_runtime_dependency 'rack', '~> 2.0.7'
40
- spec.add_runtime_dependency 'sequel', '~> 5.27.0'
41
- spec.add_runtime_dependency 'sqlite3', '~> 1.4.0'
39
+ spec.add_runtime_dependency "rake", '>= 13.0'
40
+ spec.add_runtime_dependency 'rack', '>= 2.0.6'
41
+ spec.add_runtime_dependency 'sequel', '>= 5.27.0'
42
+ spec.add_runtime_dependency 'sqlite3', '>= 1.4.0'
43
+ spec.add_runtime_dependency 'bcrypt', '>= 3.1.13'
42
44
  end
@@ -4,9 +4,12 @@ require 'yaml'
4
4
  require "sequel"
5
5
  require "json"
6
6
  require "nkf"
7
+ require "date"
8
+ require "bcrypt"
7
9
 
8
10
  require_relative 'ezframe/version'
9
11
  require_relative 'ezframe/util'
12
+ require_relative 'ezframe/ezlog'
10
13
  require_relative 'ezframe/config'
11
14
  require_relative 'ezframe/controller'
12
15
  require_relative 'ezframe/japanese_utils'
@@ -16,14 +19,17 @@ require_relative 'ezframe/database'
16
19
  require_relative 'ezframe/ht'
17
20
  require_relative 'ezframe/html'
18
21
  require_relative 'ezframe/materialize'
19
- require_relative 'ezframe/model'
20
- require_relative 'ezframe/page_kit'
21
22
  require_relative 'ezframe/page_base'
23
+ require_relative 'ezframe/editor_common'
24
+ require_relative 'ezframe/main_editor'
25
+ require_relative 'ezframe/sub_editor'
26
+ require_relative 'ezframe/single_page_editor'
22
27
  require_relative 'ezframe/template'
23
28
  require_relative 'ezframe/server'
29
+ require_relative 'ezframe/message'
24
30
  require_relative 'ezframe/auth.rb'
25
- require_relative 'ezframe/editor.rb'
26
31
  require_relative 'ezframe/loader'
32
+ require_relative 'ezframe/route'
27
33
 
28
34
 
29
35
 
@@ -1,71 +1,90 @@
1
1
  module Ezframe
2
2
  class Auth
3
3
  class << self
4
- attr_accessor :model, :user
4
+ attr_accessor :user
5
5
 
6
- def init_warden
6
+ def init
7
7
  Warden::Manager.serialize_into_session do |auth|
8
- mylog "serialize_into: #{auth.inspect}"
8
+ # EzLog.info "serialize_into: #{auth.inspect}"
9
9
  auth.user[:id]
10
10
  end
11
11
  Warden::Manager.serialize_from_session do |account|
12
- mylog "serialize_from: account = #{account}"
13
- inst = Auth.get(env['model'], account)
14
- mylog "inst = #{inst.inspect}"
12
+ # EzLog.info "serialize_from: account = #{account}"
13
+ inst = Auth.get(account)
14
+ # EzLog.info "inst = #{inst.inspect}"
15
15
  inst
16
16
  end
17
17
  Warden::Strategies.add(:mystrategy) do
18
18
  def valid?
19
- # mylog "valid?"
19
+ # EzLog.info "valid?"
20
20
  params["account"] || params["password"]
21
21
  end
22
22
 
23
23
  def authenticate!
24
- mylog "authenticate!: #{params}"
24
+ EzLog.info "mystrategy.authenticate!: user=#{user}, params=#{params}"
25
25
  if Auth.authenticate(env, params["account"], params["password"])
26
- success!(Auth.get(env['model'], params["account"]))
26
+ EzLog.info "mystrategy.authenticate!: success: user=#{user}"
27
+ success!(Auth.get(params["account"]))
27
28
  else
28
- env['x-rack.flash'].error = 'ユーザーが登録されていないか、パスワードが違っています。'
29
- fail!("authenticate failure")
29
+ EzLog.info "mystrategy.authenticate!: failed: user=#{user}"
30
+ fail!(Message[:login_failure])
30
31
  end
31
32
  end
32
33
  end
33
34
  end
34
35
 
35
- def get(model, account)
36
- new(model, account)
36
+ def get(account)
37
+ new(account)
37
38
  end
38
39
 
39
40
  def authenticate(env, account, pass)
40
- model = env["model"]
41
- raise "model is not initialized" unless model
42
- @user = model.db.dataset(:user).where(account: account).first
43
- if @user
44
- mylog "Auth: authenticate: user=#{@user.inspect}"
41
+ return nil if !pass || pass.strip.empty?
42
+ EzLog.debug("Auth.self.authenticate: account=#{account}, pass=#{pass}")
43
+ auth_conf = Config[:auth]
44
+ user_data = DB.dataset(auth_conf[:table]).where(auth_conf[:user].to_sym => account ).first
45
+ if user_data
46
+ EzLog.info "Auth: self.authenticate: has user: #{@user}"
45
47
  else
46
- mylog "authenticate: this user does not exist: #{account}"
48
+ EzLog.info "Auth.self.authenticate: this user does not exist: #{account}"
47
49
  return nil
48
50
  end
49
- mylog "env=#{env.inspect}"
50
- env['rack.session'][:user] = @user[:id]
51
- password = @user[:password]
52
- @user.delete(:password)
53
-
54
- return nil if !pass || !password
55
- !!(password == pass)
51
+ db_pass = user_data[auth_conf[:password].to_sym]
52
+ user_data.delete(:password)
53
+ return nil if !db_pass || db_pass.strip.length < 8
54
+ bcrypt = BCrypt::Password.new(db_pass)
55
+ if bcrypt == pass
56
+ env['rack.session'][:user] = user_data[:id]
57
+ @user = user_data
58
+ EzLog.debug("Auth.self.authenticate: success: password match!")
59
+ return true
60
+ else
61
+ EzLog.debug("Auth.self.authenticate: failure: password mismatch")
62
+ end
63
+ return nil
56
64
  end
57
65
  end
58
66
 
59
- attr_accessor :account, :password, :model, :user, :id
67
+ attr_accessor :account, :password, :user, :id
60
68
 
61
- def initialize(model, account)
69
+ def initialize(account)
62
70
  self.account = account
63
- @user = model.db.dataset(:user).where(Sequel.or(account: account, id: account)).first
71
+ auth_conf = Config[:auth]
72
+ dataset = DB.dataset(auth_conf[:table])
73
+ if account.is_a?(Integer)
74
+ @user = dataset.where(id: account).first
75
+ else
76
+ @user = dataset.where(auth_conf[:user].to_sym => account).first
77
+ end
64
78
  unless @user
65
- mylog "Auth.initialize: This user does not exist: #{account}"
79
+ EzLog.error "Auth.initialize: This user does not exist: #{account}"
80
+ return
66
81
  end
67
- self.password = @user[:password]
82
+ self.password = @user[auth_conf[:password].to_sym]
68
83
  @user.delete(:password)
69
84
  end
85
+
86
+ def inspect
87
+ "account=#{@account}, user=#{@user}, id=#{@id}"
88
+ end
70
89
  end
71
90
  end