ezframe 0.0.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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