Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
|
63bc26ab16 | ||
|
b319b9de93 | ||
|
2470b514c2 | ||
|
6a9437cad7 | ||
|
fa29bc75a6 | ||
|
970fdecda7 | ||
|
c19eda923e | ||
|
7257a2a5a9 | ||
|
84a78d82df | ||
|
19deb9c398 |
14 changed files with 162 additions and 168 deletions
69
.gitignore
vendored
69
.gitignore
vendored
|
@ -1,40 +1,37 @@
|
|||
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||
#
|
||||
# If you find yourself ignoring temporary files generated by your text editor
|
||||
# or operating system, you probably want to add a global ignore instead:
|
||||
# git config --global core.excludesfile '~/.gitignore_global'
|
||||
.bundle
|
||||
.rake_tasks*
|
||||
db/*.sqlite3
|
||||
log
|
||||
node_modules
|
||||
tmp/*
|
||||
!tmp/.keep
|
||||
public/assets
|
||||
public/packs
|
||||
public/system
|
||||
public/uploads
|
||||
supplier_assets/**
|
||||
vendor/bundle
|
||||
|
||||
# Ignore bundler config.
|
||||
/.bundle
|
||||
# ignore database configuration, but SHARE OTHER CONFIG FILES
|
||||
config/database.yml
|
||||
|
||||
# Ignore the default SQLite database.
|
||||
/db/*.sqlite3
|
||||
/db/*.sqlite3-*
|
||||
# IDEs, Developer tools
|
||||
.idea
|
||||
.loadpath
|
||||
.project
|
||||
.sass-cache
|
||||
.rbenv-version
|
||||
.get-dump.yml
|
||||
.bash_history
|
||||
nbproject/
|
||||
.*.sw?
|
||||
*~
|
||||
|
||||
# Ignore all logfiles and tempfiles.
|
||||
/log/*
|
||||
/tmp/*
|
||||
!/log/.keep
|
||||
!/tmp/.keep
|
||||
coverage
|
||||
tags
|
||||
|
||||
# Ignore pidfiles, but keep the directory.
|
||||
/tmp/pids/*
|
||||
!/tmp/pids/
|
||||
!/tmp/pids/.keep
|
||||
|
||||
# Ignore uploaded files in development.
|
||||
/storage/*
|
||||
!/storage/.keep
|
||||
|
||||
/public/assets
|
||||
.byebug_history
|
||||
|
||||
# Ignore master key for decrypting credentials and more.
|
||||
/config/master.key
|
||||
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
/node_modules
|
||||
/yarn-error.log
|
||||
yarn-debug.log*
|
||||
.yarn-integrity
|
||||
# Capistrano etc.
|
||||
Capfile
|
||||
config/deploy
|
||||
config/deploy.rb
|
||||
Gemfile.capistrano*
|
||||
|
|
|
@ -12,8 +12,8 @@ USER app
|
|||
|
||||
ENV BUNDLE_JOBS=4 \
|
||||
BUNDLE_PATH=/srv/app/vendor/bundle \
|
||||
GEM_PATH=/srv/app/vendor/bundle:$GEM_PATH \
|
||||
PATH=/srv/app/vendor/bundle/bin:$PATH
|
||||
GEM_PATH=/srv/app/vendor/bundle/ruby/2.7.0:$GEM_PATH \
|
||||
PATH=/srv/app/vendor/bundle/ruby/2.7.0/bin:$PATH
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -42,3 +42,5 @@ gem 'will_paginate', '~> 3.0'
|
|||
gem 'whenever', '~> 0.9', require: false
|
||||
gem 'mysql2', '>=0.5'
|
||||
gem 'base32'
|
||||
|
||||
gem "webrick", "~> 1.7" # fallback for removed puma; not included in alpine
|
||||
|
|
|
@ -230,6 +230,7 @@ GEM
|
|||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.7.0)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
|
@ -268,6 +269,7 @@ DEPENDENCIES
|
|||
web-console (>= 4.1.0)
|
||||
webdrivers
|
||||
webpacker (~> 5.0)
|
||||
webrick (~> 1.7)
|
||||
whenever (~> 0.9)
|
||||
will_paginate (~> 3.0)
|
||||
|
||||
|
|
|
@ -22,6 +22,14 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def admin_required!
|
||||
user = current_user
|
||||
if user.nil? || !user.admin?
|
||||
flash[:error] = "Not authorized!"
|
||||
redirect_to root_url
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_supplier_admin!
|
||||
@supplier = Supplier.find((params[:supplier_id] || params[:id]))
|
||||
unless current_user.has_access_to?(@supplier)
|
||||
|
|
|
@ -6,14 +6,14 @@ class SessionsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
user = User.authenticate(params[:email], params[:password])
|
||||
if user
|
||||
user = User.find_by(email: params[:email])
|
||||
if user && user.authenticate(params[:password])
|
||||
session[:user_id] = user.id
|
||||
flash[:notice] = "Logged in!"
|
||||
redirect_to root_url
|
||||
else
|
||||
flash.now[:error] = "Invalid email or password"
|
||||
render "new"
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
class UsersController < ApplicationController
|
||||
|
||||
before_action :admin_required!
|
||||
|
||||
def new
|
||||
@user=User.new
|
||||
end
|
||||
|
||||
def create
|
||||
@user=User.new(user_params)
|
||||
@user = User.new(user_params)
|
||||
if @user.save
|
||||
render 'show'
|
||||
flash[:notice] = "Konto wurde erfolgreich erstellt."
|
||||
redirect_to @user
|
||||
else
|
||||
redirect_to new_user_path
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -18,16 +22,11 @@ class UsersController < ApplicationController
|
|||
|
||||
def update
|
||||
@user = User.find(params[:id])
|
||||
attrs = user_params
|
||||
respond_to do |format|
|
||||
if @user.update(attrs)
|
||||
flash[:notice] = 'Konto wurde erfolgreich aktualisiert.'
|
||||
format.html { redirect_to user_url(@user) }
|
||||
format.xml { head :ok }
|
||||
else
|
||||
format.html { render :action => "edit" }
|
||||
format.xml { render :xml => @user.errors.to_xml }
|
||||
end
|
||||
if @user.update(user_params)
|
||||
flash[:notice] = 'Konto wurde erfolgreich aktualisiert.'
|
||||
redirect_to @user
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -50,6 +49,6 @@ class UsersController < ApplicationController
|
|||
|
||||
private
|
||||
def user_params
|
||||
params.require(:user).permit(:email, :password)
|
||||
params.require(:user).permit(:email, :password, :password_confirmation, :admin)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,38 +2,43 @@ class User < ApplicationRecord
|
|||
|
||||
has_many :user_accesses, :dependent => :destroy
|
||||
has_many :suppliers, :through => :user_accesses
|
||||
|
||||
|
||||
attr_accessor :password
|
||||
before_save :encrypt_password
|
||||
attr_reader :password
|
||||
|
||||
validates_confirmation_of :password
|
||||
validates_presence_of :password, :on => :create
|
||||
validates_presence_of :email
|
||||
validates_uniqueness_of :email
|
||||
|
||||
def self.authenticate(email, password)
|
||||
user = find_by_email(email)
|
||||
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
|
||||
user
|
||||
else
|
||||
nil
|
||||
validates :email, presence: true, uniqueness: true
|
||||
validates :password, confirmation: true
|
||||
validate do |user|
|
||||
unless user.password_hash.present? && user.password_salt.present?
|
||||
user.errors.add :password, :blank
|
||||
end
|
||||
end
|
||||
|
||||
def encrypt_password
|
||||
if password.present?
|
||||
self.password_salt = BCrypt::Engine.generate_salt
|
||||
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
|
||||
end
|
||||
def self.attributes_protected_by_default
|
||||
super + %w(password_hash password_salt)
|
||||
end
|
||||
|
||||
def has_access_to?(supplier)
|
||||
admin? or !UserAccess.first(:conditions => {:supplier_id => supplier.id, :user_id => id}).nil?
|
||||
admin? or !UserAccess.where(supplier_id: supplier.id, user_id: id).first.nil?
|
||||
end
|
||||
|
||||
def authenticate(password_plain)
|
||||
if self.password_hash == BCrypt::Engine.hash_secret(password_plain, self.password_salt)
|
||||
self
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def password=(password_plain)
|
||||
@password = password_plain
|
||||
unless password_plain.blank?
|
||||
new_salt = BCrypt::Engine.generate_salt
|
||||
self.password_hash = BCrypt::Engine.hash_secret(password_plain, new_salt)
|
||||
self.password_salt = new_salt
|
||||
end
|
||||
end
|
||||
|
||||
def admin?
|
||||
!!admin
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
= f.input :email, required: true
|
||||
= f.input :password, required: true
|
||||
= f.input :password_confirmation, required: true
|
||||
= f.input :admin, required: true
|
||||
|
||||
.form-actions
|
||||
= f.submit class: 'btn'
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# SQLite. Versions 3.8.0 and up are supported.
|
||||
# gem install sqlite3
|
||||
#
|
||||
# Ensure the SQLite 3 gem is defined in your Gemfile
|
||||
# gem 'sqlite3'
|
||||
#
|
||||
default: &default
|
||||
adapter: sqlite3
|
||||
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
||||
timeout: 5000
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
database: db/development.sqlite3
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
test:
|
||||
<<: *default
|
||||
database: db/test.sqlite3
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
database: db/production.sqlite3
|
9
config/database.yml.SAMPLE
Normal file
9
config/database.yml.SAMPLE
Normal file
|
@ -0,0 +1,9 @@
|
|||
development:
|
||||
adapter: mysql2
|
||||
encoding: utf8
|
||||
reconnect: false
|
||||
database: development
|
||||
pool: 5
|
||||
username: root
|
||||
password: secret
|
||||
host: mysql
|
|
@ -1,6 +1,4 @@
|
|||
Rails.application.routes.draw do
|
||||
get 'users/new'
|
||||
get 'users/show'
|
||||
get 'log_in' => 'sessions#new', :as => :log_in
|
||||
match 'log_out' => 'sessions#destroy', :as => :log_out, :via => [:get, :post]
|
||||
resources :sessions, :only => [:new, :create, :destroy]
|
||||
|
@ -18,8 +16,4 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
resources :users
|
||||
|
||||
match '/:controller(/:action(/:id))', :via => [:get, :post]
|
||||
match '/users', to: 'users#index', via: 'get'
|
||||
match '/users/:id', to: 'users#show', via: 'get'
|
||||
end
|
||||
|
|
5
db/migrate/20211219074758_index_users_by_unique_email.rb
Normal file
5
db/migrate/20211219074758_index_users_by_unique_email.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class IndexUsersByUniqueEmail < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_index :users, :email, unique: true
|
||||
end
|
||||
end
|
119
db/schema.rb
generated
119
db/schema.rb
generated
|
@ -1,85 +1,82 @@
|
|||
# encoding: UTF-8
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20190811115732) do
|
||||
ActiveRecord::Schema.define(version: 2021_12_19_074758) do
|
||||
|
||||
create_table "articles", :force => true do |t|
|
||||
t.string "name", :null => false
|
||||
t.integer "supplier_id", :null => false
|
||||
t.string "number"
|
||||
t.string "note"
|
||||
t.string "manufacturer"
|
||||
t.string "origin"
|
||||
t.string "unit"
|
||||
t.decimal "price", :precision => 8, :scale => 2, :default => 0.0, :null => false
|
||||
t.decimal "tax", :precision => 3, :scale => 1, :default => 7.0, :null => false
|
||||
t.decimal "deposit", :precision => 8, :scale => 2, :default => 0.0, :null => false
|
||||
t.decimal "unit_quantity", :precision => 4, :scale => 1, :default => 1.0, :null => false
|
||||
t.decimal "scale_quantity", :precision => 4, :scale => 2
|
||||
t.decimal "scale_price", :precision => 8, :scale => 2
|
||||
create_table "articles", charset: "utf8", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.integer "supplier_id", null: false
|
||||
t.string "number"
|
||||
t.string "note"
|
||||
t.string "manufacturer"
|
||||
t.string "origin"
|
||||
t.string "unit"
|
||||
t.decimal "price", precision: 8, scale: 2, default: "0.0", null: false
|
||||
t.decimal "tax", precision: 3, scale: 1, default: "7.0", null: false
|
||||
t.decimal "deposit", precision: 8, scale: 2, default: "0.0", null: false
|
||||
t.decimal "unit_quantity", precision: 4, scale: 1, default: "1.0", null: false
|
||||
t.decimal "scale_quantity", precision: 4, scale: 2
|
||||
t.decimal "scale_price", precision: 8, scale: 2
|
||||
t.datetime "created_on"
|
||||
t.datetime "updated_on"
|
||||
t.string "category"
|
||||
t.string "category"
|
||||
t.index ["name"], name: "index_articles_on_name"
|
||||
t.index ["number", "supplier_id"], name: "index_articles_on_number_and_supplier_id", unique: true
|
||||
end
|
||||
|
||||
add_index "articles", ["name"], :name => "index_articles_on_name"
|
||||
add_index "articles", ["number", "supplier_id"], :name => "index_articles_on_number_and_supplier_id", :unique => true
|
||||
|
||||
create_table "suppliers", :force => true do |t|
|
||||
t.string "name", :null => false
|
||||
t.string "address", :null => false
|
||||
t.string "phone", :null => false
|
||||
t.string "phone2"
|
||||
t.string "fax"
|
||||
t.string "email"
|
||||
t.string "url"
|
||||
t.string "delivery_days"
|
||||
t.string "note"
|
||||
create_table "suppliers", charset: "utf8", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "address", null: false
|
||||
t.string "phone", null: false
|
||||
t.string "phone2"
|
||||
t.string "fax"
|
||||
t.string "email"
|
||||
t.string "url"
|
||||
t.string "delivery_days"
|
||||
t.string "note"
|
||||
t.datetime "created_on"
|
||||
t.datetime "updated_on"
|
||||
t.boolean "ftp_sync", :default => false
|
||||
t.string "ftp_host"
|
||||
t.string "ftp_user"
|
||||
t.string "ftp_password"
|
||||
t.string "ftp_type", :default => "bnn", :null => false
|
||||
t.string "ftp_regexp", :default => "^([.]/)?PL"
|
||||
t.boolean "mail_sync"
|
||||
t.string "mail_from"
|
||||
t.string "mail_subject"
|
||||
t.string "mail_type"
|
||||
t.string "salt", :null => false
|
||||
t.boolean "ftp_sync", default: false
|
||||
t.string "ftp_host"
|
||||
t.string "ftp_user"
|
||||
t.string "ftp_password"
|
||||
t.string "ftp_type", default: "bnn", null: false
|
||||
t.string "ftp_regexp", default: "^([.]/)?PL"
|
||||
t.boolean "mail_sync"
|
||||
t.string "mail_from"
|
||||
t.string "mail_subject"
|
||||
t.string "mail_type"
|
||||
t.string "salt", null: false
|
||||
t.index ["name"], name: "index_suppliers_on_name", unique: true
|
||||
end
|
||||
|
||||
add_index "suppliers", ["name"], :name => "index_suppliers_on_name", :unique => true
|
||||
|
||||
create_table "user_accesses", :force => true do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "supplier_id"
|
||||
create_table "user_accesses", charset: "utf8", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "supplier_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["supplier_id"], name: "index_user_accesses_on_supplier_id"
|
||||
t.index ["user_id", "supplier_id"], name: "index_user_accesses_on_user_id_and_supplier_id"
|
||||
t.index ["user_id"], name: "index_user_accesses_on_user_id"
|
||||
end
|
||||
|
||||
add_index "user_accesses", ["supplier_id"], :name => "index_user_accesses_on_supplier_id"
|
||||
add_index "user_accesses", ["user_id", "supplier_id"], :name => "index_user_accesses_on_user_id_and_supplier_id"
|
||||
add_index "user_accesses", ["user_id"], :name => "index_user_accesses_on_user_id"
|
||||
|
||||
create_table "users", :force => true do |t|
|
||||
t.string "email"
|
||||
t.string "password_hash"
|
||||
t.string "password_salt"
|
||||
create_table "users", charset: "utf8", force: :cascade do |t|
|
||||
t.string "email"
|
||||
t.string "password_hash"
|
||||
t.string "password_salt"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "admin", :default => false
|
||||
t.boolean "admin", default: false
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue