mirror of
https://github.com/TracksApp/tracks.git
synced 2025-09-22 05:50:47 +02:00
Merge remote-tracking branch 'origin/master' into dependabot/bundler/jquery-ui-rails-6.0.1
This commit is contained in:
commit
90653568ef
55 changed files with 594 additions and 227 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -21,8 +21,9 @@
|
||||||
/tmp
|
/tmp
|
||||||
config/deploy.rb
|
config/deploy.rb
|
||||||
config/site.yml
|
config/site.yml
|
||||||
|
config/database.yml
|
||||||
db/data.yml
|
db/data.yml
|
||||||
nbproject
|
nbproject
|
||||||
rerun.txt
|
rerun.txt
|
||||||
tags
|
tags
|
||||||
.skip-docker
|
.use-docker
|
||||||
|
|
|
@ -17,9 +17,10 @@ COPY . /app/
|
||||||
COPY config/database.docker.yml /app/config/database.yml
|
COPY config/database.docker.yml /app/config/database.yml
|
||||||
COPY config/site.docker.yml /app/config/site.yml
|
COPY config/site.docker.yml /app/config/site.yml
|
||||||
|
|
||||||
COPY docker-startserver.sh /
|
RUN RAILS_ENV=production bundle exec rake assets:precompile
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
#CMD ["rails", "server", "-e", "production", "-b", "0.0.0.0"]
|
CMD ["rails", "server", "-b", "0.0.0.0"]
|
||||||
CMD ["./docker-startserver.sh"]
|
|
||||||
|
|
8
Gemfile
8
Gemfile
|
@ -29,14 +29,14 @@ gem "RedCloth"
|
||||||
gem "sanitize", "~> 5.2"
|
gem "sanitize", "~> 5.2"
|
||||||
gem "will_paginate"
|
gem "will_paginate"
|
||||||
gem "acts_as_list"
|
gem "acts_as_list"
|
||||||
gem "aasm", '~> 3.4.0'
|
gem "aasm", '~> 4.12.3'
|
||||||
gem "htmlentities"
|
gem "htmlentities"
|
||||||
gem "rails_autolink"
|
gem "rails_autolink"
|
||||||
gem 'puma', '~> 4.3'
|
gem 'puma', '~> 4.3'
|
||||||
gem 'paperclip'
|
gem 'paperclip'
|
||||||
|
|
||||||
# To use ActiveModel has_secure_password
|
# To use ActiveModel has_secure_password
|
||||||
gem 'bcrypt', '~> 3.1.13'
|
gem 'bcrypt', '~> 3.1.15'
|
||||||
|
|
||||||
gem 'chartjs-ror', :git => 'git://github.com/ZeiP/chartjs-ror.git'
|
gem 'chartjs-ror', :git => 'git://github.com/ZeiP/chartjs-ror.git'
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ group :development do
|
||||||
gem "spring"
|
gem "spring"
|
||||||
gem "yard"
|
gem "yard"
|
||||||
|
|
||||||
gem 'tolk', '~> 3.2.1'
|
gem 'tolk', '~> 4.0.0'
|
||||||
|
|
||||||
gem "bullet"
|
gem "bullet"
|
||||||
gem "rack-mini-profiler"
|
gem "rack-mini-profiler"
|
||||||
|
@ -63,7 +63,7 @@ end
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'byebug'
|
gem 'byebug'
|
||||||
gem 'listen'
|
gem 'listen'
|
||||||
gem "rubocop", "~> 0.88", require: false
|
gem "rubocop", "~> 0.89", require: false
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|
37
Gemfile.lock
37
Gemfile.lock
|
@ -9,7 +9,8 @@ GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
RedCloth (4.3.2)
|
RedCloth (4.3.2)
|
||||||
aasm (3.4.0)
|
aasm (4.12.3)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
actioncable (5.2.4.3)
|
actioncable (5.2.4.3)
|
||||||
actionpack (= 5.2.4.3)
|
actionpack (= 5.2.4.3)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
|
@ -65,7 +66,7 @@ GEM
|
||||||
autoprefixer-rails (9.4.7)
|
autoprefixer-rails (9.4.7)
|
||||||
execjs
|
execjs
|
||||||
backport (1.1.2)
|
backport (1.1.2)
|
||||||
bcrypt (3.1.13)
|
bcrypt (3.1.15)
|
||||||
benchmark (0.1.0)
|
benchmark (0.1.0)
|
||||||
bootstrap-sass (3.4.1)
|
bootstrap-sass (3.4.1)
|
||||||
autoprefixer-rails (>= 5.2.1)
|
autoprefixer-rails (>= 5.2.1)
|
||||||
|
@ -105,7 +106,7 @@ GEM
|
||||||
globalid (0.4.2)
|
globalid (0.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
htmlentities (4.3.4)
|
htmlentities (4.3.4)
|
||||||
i18n (1.8.3)
|
i18n (1.8.4)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
jaro_winkler (1.5.4)
|
jaro_winkler (1.5.4)
|
||||||
jquery-rails (4.4.0)
|
jquery-rails (4.4.0)
|
||||||
|
@ -154,7 +155,7 @@ GEM
|
||||||
puma (4.3.5)
|
puma (4.3.5)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
rack (2.2.3)
|
rack (2.2.3)
|
||||||
rack-mini-profiler (2.0.1)
|
rack-mini-profiler (2.0.4)
|
||||||
rack (>= 1.2.0)
|
rack (>= 1.2.0)
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
|
@ -190,7 +191,7 @@ GEM
|
||||||
thor (>= 0.19.0, < 2.0)
|
thor (>= 0.19.0, < 2.0)
|
||||||
rainbow (3.0.0)
|
rainbow (3.0.0)
|
||||||
rake (13.0.1)
|
rake (13.0.1)
|
||||||
rb-fsevent (0.10.3)
|
rb-fsevent (0.10.4)
|
||||||
rb-inotify (0.10.1)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
ref (2.0.0)
|
ref (2.0.0)
|
||||||
|
@ -202,17 +203,17 @@ GEM
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.9.0)
|
rspec-support (~> 3.9.0)
|
||||||
rspec-support (3.9.3)
|
rspec-support (3.9.3)
|
||||||
rubocop (0.88.0)
|
rubocop (0.89.1)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 2.7.1.1)
|
parser (>= 2.7.1.1)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.7)
|
regexp_parser (>= 1.7)
|
||||||
rexml
|
rexml
|
||||||
rubocop-ast (>= 0.1.0, < 1.0)
|
rubocop-ast (>= 0.3.0, < 1.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 2.0)
|
unicode-display_width (>= 1.4.0, < 2.0)
|
||||||
rubocop-ast (0.1.0)
|
rubocop-ast (0.3.0)
|
||||||
parser (>= 2.7.0.1)
|
parser (>= 2.7.1.4)
|
||||||
ruby-progressbar (1.10.1)
|
ruby-progressbar (1.10.1)
|
||||||
rubyzip (2.0.0)
|
rubyzip (2.0.0)
|
||||||
safe_yaml (1.0.5)
|
safe_yaml (1.0.5)
|
||||||
|
@ -237,11 +238,11 @@ GEM
|
||||||
selenium-webdriver (3.142.7)
|
selenium-webdriver (3.142.7)
|
||||||
childprocess (>= 0.5, < 4.0)
|
childprocess (>= 0.5, < 4.0)
|
||||||
rubyzip (>= 1.2.2)
|
rubyzip (>= 1.2.2)
|
||||||
simplecov (0.18.5)
|
simplecov (0.19.0)
|
||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
simplecov-html (~> 0.11)
|
simplecov-html (~> 0.11)
|
||||||
simplecov-html (0.12.2)
|
simplecov-html (0.12.2)
|
||||||
solargraph (0.39.11)
|
solargraph (0.39.14)
|
||||||
backport (~> 1.1)
|
backport (~> 1.1)
|
||||||
benchmark
|
benchmark
|
||||||
bundler (>= 1.17.2)
|
bundler (>= 1.17.2)
|
||||||
|
@ -272,17 +273,17 @@ GEM
|
||||||
thor (1.0.1)
|
thor (1.0.1)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.10)
|
tilt (2.0.10)
|
||||||
tolk (3.2.1)
|
tolk (4.0.0)
|
||||||
rails (>= 5.0)
|
rails (>= 5.0)
|
||||||
safe_yaml (>= 0.8.6)
|
safe_yaml (>= 0.8.6)
|
||||||
sass
|
sassc
|
||||||
tzinfo (1.2.7)
|
tzinfo (1.2.7)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (4.2.0)
|
uglifier (4.2.0)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
unicode-display_width (1.7.0)
|
unicode-display_width (1.7.0)
|
||||||
uniform_notifier (1.13.0)
|
uniform_notifier (1.13.0)
|
||||||
websocket-driver (0.7.2)
|
websocket-driver (0.7.3)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
will_paginate (3.3.0)
|
will_paginate (3.3.0)
|
||||||
|
@ -293,11 +294,11 @@ PLATFORMS
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
RedCloth
|
RedCloth
|
||||||
aasm (~> 3.4.0)
|
aasm (~> 4.12.3)
|
||||||
actionpack-xml_parser (~> 2.0)
|
actionpack-xml_parser (~> 2.0)
|
||||||
activemodel-serializers-xml (~> 1.0.1)
|
activemodel-serializers-xml (~> 1.0.1)
|
||||||
acts_as_list
|
acts_as_list
|
||||||
bcrypt (~> 3.1.13)
|
bcrypt (~> 3.1.15)
|
||||||
bootstrap-sass (= 3.4.1)
|
bootstrap-sass (= 3.4.1)
|
||||||
bullet
|
bullet
|
||||||
byebug
|
byebug
|
||||||
|
@ -322,7 +323,7 @@ DEPENDENCIES
|
||||||
rails-dom-testing (~> 2.0.0)
|
rails-dom-testing (~> 2.0.0)
|
||||||
rails_autolink
|
rails_autolink
|
||||||
rspec-expectations
|
rspec-expectations
|
||||||
rubocop (~> 0.88)
|
rubocop (~> 0.89)
|
||||||
sanitize (~> 5.2)
|
sanitize (~> 5.2)
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
selenium-webdriver (~> 3.142)
|
selenium-webdriver (~> 3.142)
|
||||||
|
@ -331,7 +332,7 @@ DEPENDENCIES
|
||||||
spring
|
spring
|
||||||
sqlite3
|
sqlite3
|
||||||
therubyracer
|
therubyracer
|
||||||
tolk (~> 3.2.1)
|
tolk (~> 4.0.0)
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
will_paginate
|
will_paginate
|
||||||
yard
|
yard
|
||||||
|
|
|
@ -53,3 +53,7 @@ body {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
background-color: $body-bg;
|
background-color: $body-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-datepicker {
|
||||||
|
z-index: 999999 !important;
|
||||||
|
}
|
||||||
|
|
|
@ -1349,10 +1349,6 @@ div.auto_complete {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-datepicker {
|
|
||||||
z-index: 1000 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui-autocomplete-loading {
|
.ui-autocomplete-loading {
|
||||||
background: white image-url('ui-anim_basic_16x16.gif') right center no-repeat;
|
background: white image-url('ui-anim_basic_16x16.gif') right center no-repeat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ body {
|
||||||
|
|
||||||
.login-wrapper {
|
.login-wrapper {
|
||||||
@include make-row();
|
@include make-row();
|
||||||
|
.footer {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-box {
|
.login-box {
|
||||||
|
@ -19,11 +22,21 @@ body {
|
||||||
@include make-sm-column-offset(3);
|
@include make-sm-column-offset(3);
|
||||||
margin: 2em auto 1em;
|
margin: 2em auto 1em;
|
||||||
background-color: rgba(0, 0, 0, 0.75);
|
background-color: rgba(0, 0, 0, 0.75);
|
||||||
color: #eaeaea;
|
|
||||||
padding: 0 0 1em 0;
|
padding: 0 0 1em 0;
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5), 0 2px 3px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5), 0 2px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
color: #eaeaea;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #eaeaea;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signup-prompt {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media(min-width: $screen-sm-min) {
|
@media(min-width: $screen-sm-min) {
|
||||||
.login-box {
|
.login-box {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
@ -34,7 +47,7 @@ body {
|
||||||
padding: 1em 0;
|
padding: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-form {
|
.login-form, .signup-form {
|
||||||
@include make-xs-column(12);
|
@include make-xs-column(12);
|
||||||
@include make-sm-column(8);
|
@include make-sm-column(8);
|
||||||
@include make-sm-column-offset(2)
|
@include make-sm-column-offset(2)
|
||||||
|
|
|
@ -154,6 +154,13 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def admin_or_self_login_required
|
||||||
|
unless User.find(session['user_id']).is_admin || session['user_id'] == params[:id].to_i
|
||||||
|
render :body => t('errors.user_unauthorized'), :status => 401
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def redirect_back_or_home
|
def redirect_back_or_home
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_back_or_default root_url }
|
format.html { redirect_back_or_default root_url }
|
||||||
|
|
|
@ -12,6 +12,10 @@ class IntegrationsController < ApplicationController
|
||||||
@page_title = 'TRACKS::REST API Documentation'
|
@page_title = 'TRACKS::REST API Documentation'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def help
|
||||||
|
@page_title = 'TRACKS::Help'
|
||||||
|
end
|
||||||
|
|
||||||
def search_plugin
|
def search_plugin
|
||||||
@icon_data = [File.open(File.join(Rails.root, 'app', 'assets', 'images', 'done.png')).read].
|
@icon_data = [File.open(File.join(Rails.root, 'app', 'assets', 'images', 'done.png')).read].
|
||||||
pack('m').gsub(/\n/, '')
|
pack('m').gsub(/\n/, '')
|
||||||
|
|
|
@ -14,6 +14,7 @@ class LoginController < ApplicationController
|
||||||
case request.method
|
case request.method
|
||||||
when 'POST'
|
when 'POST'
|
||||||
if @user = User.authenticate(params['user_login'], params['user_password'])
|
if @user = User.authenticate(params['user_login'], params['user_password'])
|
||||||
|
@user.update_attribute(:last_login_at, Time.now)
|
||||||
return handle_post_success
|
return handle_post_success
|
||||||
else
|
else
|
||||||
handle_post_failure
|
handle_post_failure
|
||||||
|
|
|
@ -44,7 +44,7 @@ private
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
params.require(:user).permit(:login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url)
|
params.require(:user).permit(:login, :first_name, :last_name, :email, :password_confirmation, :password, :auth_type, :open_id_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Display notification if preferences are successful updated
|
# Display notification if preferences are successful updated
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
|
|
||||||
before_action :admin_login_required, :only => [ :index, :show, :destroy ]
|
before_action :admin_login_required, :only => [ :index, :show ]
|
||||||
|
before_action :admin_or_self_login_required, :only => [ :destroy ]
|
||||||
skip_before_action :login_required, :only => [ :new, :create ]
|
skip_before_action :login_required, :only => [ :new, :create ]
|
||||||
prepend_before_action :login_optional, :only => [ :new, :create ]
|
prepend_before_action :login_optional, :only => [ :new, :create ]
|
||||||
|
|
||||||
|
@ -76,10 +77,14 @@ class UsersController < ApplicationController
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless params['approve_tos'] == 'on' || SITE_CONFIG['tos_link'].blank?
|
||||||
|
render_failure "You have to accept the terms of service to sign up!"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
user = User.new(user_params)
|
user = User.new(user_params)
|
||||||
|
|
||||||
unless user.valid?
|
unless user.valid?
|
||||||
session['new_user'] = user
|
|
||||||
redirect_to signup_path
|
redirect_to signup_path
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -99,13 +104,18 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
format.xml do
|
format.xml do
|
||||||
unless current_user && current_user.is_admin
|
unless current_user && current_user.is_admin
|
||||||
render :body => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
|
render :body => t('errors.user_unauthorized'), :status => 401
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
unless check_create_user_params
|
unless check_create_user_params
|
||||||
render_failure "Expected post format is valid xml like so: <user><login>username</login><password>abc123</password></user>.", 400
|
render_failure "Expected post format is valid xml like so: <user><login>username</login><password>abc123</password></user>.", 400
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
unless user_params['approve_tos'] == 'on' || SITE_CONFIG['tos_link'].blank?
|
||||||
|
render_failure "You have to accept the terms of service to sign up!"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
user = User.new(user_params)
|
user = User.new(user_params)
|
||||||
user.password_confirmation = user_params[:password]
|
user.password_confirmation = user_params[:password]
|
||||||
saved = user.save
|
saved = user.save
|
||||||
|
@ -122,8 +132,14 @@ class UsersController < ApplicationController
|
||||||
# DELETE /users/id DELETE /users/id.xml
|
# DELETE /users/id DELETE /users/id.xml
|
||||||
def destroy
|
def destroy
|
||||||
@deleted_user = User.find(params[:id])
|
@deleted_user = User.find(params[:id])
|
||||||
|
|
||||||
|
# Remove the user
|
||||||
@saved = @deleted_user.destroy
|
@saved = @deleted_user.destroy
|
||||||
@total_users = User.count
|
|
||||||
|
# Log out the user if they've deleted their own user and it succeeded.
|
||||||
|
if @saved && current_user == @deleted_user
|
||||||
|
logout_user
|
||||||
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
|
@ -132,10 +148,18 @@ class UsersController < ApplicationController
|
||||||
else
|
else
|
||||||
notify :error, t('users.failed_to_delete_user', :username => @deleted_user.login)
|
notify :error, t('users.failed_to_delete_user', :username => @deleted_user.login)
|
||||||
end
|
end
|
||||||
redirect_to users_url
|
if current_user == @deleted_user
|
||||||
|
redirect_to login
|
||||||
|
else
|
||||||
|
redirect_to users_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
format.js do
|
||||||
|
@total_users = User.count
|
||||||
|
end
|
||||||
|
format.xml do
|
||||||
|
head :ok
|
||||||
end
|
end
|
||||||
format.js
|
|
||||||
format.xml { head :ok }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -178,7 +202,7 @@ class UsersController < ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
params.require(:user).permit(:login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url)
|
params.require(:user).permit(:login, :first_name, :last_name, :email, :password_confirmation, :password, :auth_type, :open_id_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_new_user
|
def get_new_user
|
||||||
|
|
|
@ -18,4 +18,14 @@ module PreferencesHelper
|
||||||
pref(model, pref_name) { text_field(model, pref_name, class: "form-control") }
|
pref(model, pref_name) { text_field(model, pref_name, class: "form-control") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def profile_delete_user(user)
|
||||||
|
return link_to(
|
||||||
|
t('users.destroy_user'),
|
||||||
|
url_for({:controller => 'users', :action => 'destroy', :id => user.id}),
|
||||||
|
{:id => "delete_user_#{user.id}",
|
||||||
|
:class => "delete_user_button btn btn-danger",
|
||||||
|
:title => t('users.destroy_user'),
|
||||||
|
:x_confirm_message => t('users.destroy_confirmation', :login => user.login)
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ class User < ApplicationRecord
|
||||||
|
|
||||||
#for will_paginate plugin
|
#for will_paginate plugin
|
||||||
cattr_accessor :per_page
|
cattr_accessor :per_page
|
||||||
@@per_page = 5
|
@@per_page = 10
|
||||||
|
|
||||||
has_many(:contexts, -> { order 'position ASC' }, dependent: :delete_all) do
|
has_many(:contexts, -> { order 'position ASC' }, dependent: :delete_all) do
|
||||||
def find_by_params(params)
|
def find_by_params(params)
|
||||||
|
@ -107,6 +107,7 @@ class User < ApplicationRecord
|
||||||
validates_length_of :login, within: 3..80
|
validates_length_of :login, within: 3..80
|
||||||
validates_uniqueness_of :login, on: :create
|
validates_uniqueness_of :login, on: :create
|
||||||
validate :validate_auth_type
|
validate :validate_auth_type
|
||||||
|
validates :email, :allow_blank => true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
||||||
|
|
||||||
before_create :crypt_password, :generate_token
|
before_create :crypt_password, :generate_token
|
||||||
before_update :crypt_password
|
before_update :crypt_password
|
||||||
|
|
13
app/views/integrations/help.html.erb
Normal file
13
app/views/integrations/help.html.erb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<h1>Help</h1>
|
||||||
|
|
||||||
|
<p>You can find information on the usage in the <a href="https://github.com/TracksApp/tracks/wiki/User-manual">User manual</a> in the project GitHub wiki.</p>
|
||||||
|
|
||||||
|
<p>If you encounter a bug or have a feature request, please report it in the <a href="https://github.com/TracksApp/tracks/issues">issue queue</a>.</p>
|
||||||
|
|
||||||
|
<p>We gladly welcome all contributions to Tracks. Check the <a href="https://www.getontracks.org/contribute/">project website</a> for further information. You can also come discuss with the community:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://groups.google.com/group/TracksApp">Mailing list</a></li>
|
||||||
|
<li><a href="https://gitter.im/TracksApp/tracks">Gitter chat</a></li>
|
||||||
|
<li><a href="https://webchat.freenode.net/#Tracks">IRC channel #Tracks@FreeNode</li>
|
||||||
|
</ul>
|
|
@ -29,6 +29,11 @@
|
||||||
</div>
|
</div>
|
||||||
<%= submit_tag t("login.sign_in"), class: "btn btn-default" %>
|
<%= submit_tag t("login.sign_in"), class: "btn btn-default" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% if SITE_CONFIG['open_signups'] -%>
|
||||||
|
<div class="signup-prompt">
|
||||||
|
<%= link_to t('login.signup_prompt'), url_for(:action => 'new', :controller => 'users') %>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<%= pref_with_text_field 'user', 'last_name' %>
|
<%= pref_with_text_field 'user', 'last_name' %>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<%= pref_with_text_field 'user', 'email' %>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<%= pref_with_select_field('prefs', 'locale', I18n.available_locales.map {|l| l.to_s}) %>
|
<%= pref_with_select_field('prefs', 'locale', I18n.available_locales.map {|l| l.to_s}) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
4
app/views/preferences/_remove_account.html.erb
Normal file
4
app/views/preferences/_remove_account.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<p><%= t 'preferences.remove_introduction' %></p>
|
||||||
|
<div class="form-group">
|
||||||
|
<%= profile_delete_user(@user) %>
|
||||||
|
</div>
|
|
@ -21,16 +21,20 @@
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
<%= link_to t('preferences.tabs.tracks_behavior'), "#behavior", data: { toggle: "tab" } %>
|
<%= link_to t('preferences.tabs.tracks_behavior'), "#behavior", data: { toggle: "tab" } %>
|
||||||
</li>
|
</li>
|
||||||
|
<li role="presentation">
|
||||||
|
<%= link_to t('preferences.tabs.remove_account'), "#remove_account", data: { toggle: "tab" } %>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div role="tabpanel" class="tab-pane active" id="profile"><%= render :partial => 'profile'%></div>
|
<div role="tabpanel" class="tab-pane active" id="profile"><%= render :partial => 'profile'%></div>
|
||||||
<div role="tabpanel" class="tab-pane" id="authentication"><%= render :partial => 'authentication'%></div>
|
<div role="tabpanel" class="tab-pane" id="authentication"><%= render :partial => 'authentication'%></div>
|
||||||
<div role="tabpanel" class="tab-pane" id="date_and_time"><%= render :partial => 'date_and_time'%></div>
|
<div role="tabpanel" class="tab-pane" id="date_and_time"><%= render :partial => 'date_and_time'%></div>
|
||||||
<div role="tabpanel" class="tab-pane" id="behavior"><%= render :partial => 'tracks_behavior'%></div>
|
<div role="tabpanel" class="tab-pane" id="behavior"><%= render :partial => 'tracks_behavior'%></div>
|
||||||
|
<div role="tabpanel" class="tab-pane" id="remove_account"><%= render :partial => 'remove_account'%></div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group" role="group" aria-label="Basic example">
|
||||||
|
<button type="submit" id="prefs_submit" class="btn btn-default"><%= t('common.update') %></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" id="prefs_submit" class="btn btn-default"><%= t('common.update') %></button>
|
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
<%= t('layouts.navigation.help') %> <span class="caret"></span>
|
<%= t('layouts.navigation.help') %> <span class="caret"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
|
<li><%= link_to t('layouts.navigation.help_page'), help_path %></li>
|
||||||
<li><%= link_to t('layouts.navigation.integrations_'), integrations_path %></li>
|
<li><%= link_to t('layouts.navigation.integrations_'), integrations_path %></li>
|
||||||
<li><%= link_to t('layouts.navigation.api_docs'), rest_api_docs_path %></li>
|
<li><%= link_to t('layouts.navigation.api_docs'), rest_api_docs_path %></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -6,24 +6,30 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th><%= User.human_attribute_name('login') %></th>
|
<th><%= User.human_attribute_name('login') %></th>
|
||||||
<th><%= User.human_attribute_name('display_name') %></th>
|
<th><%= User.human_attribute_name('display_name') %></th>
|
||||||
|
<th><%= User.human_attribute_name('email') %></th>
|
||||||
<th><%= User.human_attribute_name('auth_type') %></th>
|
<th><%= User.human_attribute_name('auth_type') %></th>
|
||||||
<th><%= User.human_attribute_name('open_id_url') %></th>
|
<th><%= User.human_attribute_name('open_id_url') %></th>
|
||||||
<th><%= t('users.total_actions') %></th>
|
<th><%= t('users.total_actions') %></th>
|
||||||
<th><%= t('users.total_contexts') %></th>
|
<th><%= t('users.total_contexts') %></th>
|
||||||
<th><%= t('users.total_projects') %></th>
|
<th><%= t('users.total_projects') %></th>
|
||||||
<th><%= t('users.total_notes') %></th>
|
<th><%= t('users.total_notes') %></th>
|
||||||
|
<th><%= User.human_attribute_name('created_at') %></th>
|
||||||
|
<th><%= User.human_attribute_name('last_login_at') %></th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
<% for user in @users %>
|
<% for user in @users %>
|
||||||
<tr <%= "class=\"highlight\"" if user.is_admin? %> id="user-<%= user.id %>">
|
<tr <%= "class=\"highlight\"" if user.is_admin? %> id="user-<%= user.id %>">
|
||||||
<td><%=h user.login %></td>
|
<td><%=h user.login %></td>
|
||||||
<td><%=h user.display_name %></td>
|
<td><%=h user.display_name %></td>
|
||||||
|
<td><%=h user.email %></td>
|
||||||
<td><%= h user.auth_type %></td>
|
<td><%= h user.auth_type %></td>
|
||||||
<td><%= h user.open_id_url || '-' %></td>
|
<td><%= h user.open_id_url || '-' %></td>
|
||||||
<td><%= h user.todos.size %></td>
|
<td><%= h user.todos.size %></td>
|
||||||
<td><%= h user.contexts.size %></td>
|
<td><%= h user.contexts.size %></td>
|
||||||
<td><%= h user.projects.size %></td>
|
<td><%= h user.projects.size %></td>
|
||||||
<td><%= h user.notes.size %></td>
|
<td><%= h user.notes.size %></td>
|
||||||
|
<td><%= format_date(user.created_at) %></td>
|
||||||
|
<td><%= format_date(user.last_login_at) %></td>
|
||||||
<td><%= !user.is_admin? ? remote_delete_user(user) : " ".html_safe %></td>
|
<td><%= !user.is_admin? ? remote_delete_user(user) : " ".html_safe %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,31 +1,55 @@
|
||||||
<div title="<%= t('users.account_signup') %>" id="signupform" class="form">
|
<div class="container-fluid">
|
||||||
<%= form_tag :action=> "create" do %>
|
<div class="row">
|
||||||
|
<div class="login-flash">
|
||||||
|
<%= bootstrap_flash :close_button => false %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="login-wrapper">
|
||||||
|
<div class="login-box">
|
||||||
|
<div class="icon-box">
|
||||||
|
<div class="tracks-icon"><div class="tracks-icon-text">10</div>
|
||||||
|
</div>
|
||||||
|
<div title="<%= t('users.account_signup') %>" id="signupform" class="signup-form" class="form">
|
||||||
|
<%= form_tag :action=> "create" do %>
|
||||||
|
|
||||||
<%= get_list_of_error_messages_for @user %><br/>
|
<%= get_list_of_error_messages_for @user %><br/>
|
||||||
|
|
||||||
<%= render_flash %>
|
<%= render_flash %>
|
||||||
|
|
||||||
<h3><%= @heading -%></h3>
|
<h3><%= @heading -%></h3>
|
||||||
|
|
||||||
<table>
|
<div class="label-element-combo">
|
||||||
<tr>
|
<%= label_tag "user_login", t('users.desired_login') %>
|
||||||
<td><label for="user_login"><%= t('users.desired_login') %>:</label></td>
|
<%= text_field "user", "login", class: "form-control" %>
|
||||||
<td> <%= text_field "user", "login", :size => 20 %></td>
|
</div>
|
||||||
</tr>
|
<div class="label-element-combo">
|
||||||
<tr>
|
<%= label_tag "user_email", t('users.email_address') %>
|
||||||
<td><label for="user_password"><%= t('users.choose_password') %>:</label></td>
|
<%= text_field "user", "email", class: "form-control" %>
|
||||||
<td><%= password_field "user", "password", :size => 20 %></td>
|
</div>
|
||||||
</tr>
|
<div class="label-element-combo">
|
||||||
<tr>
|
<%= label_tag "user_password", t('users.choose_password') %>
|
||||||
<td><label for="user_password_confirmation"><%= t('users.confirm_password') %>:</label></td>
|
<%= password_field "user", "password", class: "form-control" %>
|
||||||
<td><%= password_field "user", "password_confirmation", :size => 20 %></td>
|
</div>
|
||||||
</tr>
|
<div class="label-element-combo">
|
||||||
<tr>
|
<%= label_tag "user_password_confirmation", t('users.confirm_password') %>
|
||||||
<td></td>
|
<%= password_field "user", "password_confirmation", class: "form-control" %>
|
||||||
<td><input type="submit" id="signup" value="<%= t('users.signup') %> »" class="primary" /></td>
|
</div>
|
||||||
</tr>
|
<% unless SITE_CONFIG['tos_link'].blank? -%>
|
||||||
</table>
|
<div class="label-element-combo">
|
||||||
<%end-%>
|
<div class="checkbox">
|
||||||
|
<input name="approve_tos" id="approve_tos" type="checkbox" />
|
||||||
|
<label for="approve_tos"><%= t("users.approve_tos") %></label>
|
||||||
|
(<a href="<%= SITE_CONFIG['tos_link'] %>"><%= t('users.tos_link') %></a>)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
<%= submit_tag t("users.signup"), class: "btn btn-default" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<%= render :partial => "shared/footer" %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
unless ENV["RAILS_ENV"] == "production" || File.exist?("#{__dir__}/../.skip-docker")
|
if File.exist?("#{__dir__}/../.use-docker")
|
||||||
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
||||||
end
|
end
|
||||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
unless ENV["RAILS_ENV"] == "production" || File.exist?("#{__dir__}/../.skip-docker")
|
if File.exist?("#{__dir__}/../.use-docker")
|
||||||
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
2
bin/rake
2
bin/rake
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
unless ENV["RAILS_ENV"] == "production" || File.exist?("#{__dir__}/../.skip-docker")
|
if File.exist?("#{__dir__}/../.use-docker")
|
||||||
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
||||||
end
|
end
|
||||||
require_relative '../config/boot'
|
require_relative '../config/boot'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
unless ENV["RAILS_ENV"] == "production" || File.exist?("#{__dir__}/../.skip-docker")
|
if File.exist?("#{__dir__}/../.use-docker")
|
||||||
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
exec("#{__dir__}/../script/docker-environment", $PROGRAM_NAME, *ARGV) unless File.exist?("/etc/app-env")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,24 @@
|
||||||
#development:
|
test:
|
||||||
# adapter: mysql2
|
|
||||||
# database: tracks_dev
|
|
||||||
# # set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# # like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# # encoding: utf8
|
|
||||||
# host: docker
|
|
||||||
# port: 3307
|
|
||||||
# username: tracks_dev
|
|
||||||
# password: FqUKMWPz5mh8UPhypZvq
|
|
||||||
|
|
||||||
#development:
|
|
||||||
# adapter: postgresql
|
|
||||||
# database: tracks_dev
|
|
||||||
# # set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# # like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# # encoding: utf8
|
|
||||||
# host: docker
|
|
||||||
# port: 5432
|
|
||||||
# username: tracks_dev
|
|
||||||
# password: password
|
|
||||||
|
|
||||||
#development:
|
|
||||||
# adapter: sqlite3
|
|
||||||
# database: db.sqlite
|
|
||||||
|
|
||||||
#test:
|
|
||||||
# adapter: mysql2
|
|
||||||
# database: tracks_test
|
|
||||||
# # set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# # like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# # encoding: utf8
|
|
||||||
# host: docker
|
|
||||||
# port: 3307
|
|
||||||
# username: tracks_tst
|
|
||||||
# password: 9rMNV4y6RVcqmJTo2QoR
|
|
||||||
|
|
||||||
# Production config is disabled by default
|
|
||||||
#
|
|
||||||
development:
|
|
||||||
adapter: <%= ENV.fetch('DATABASE_TYPE') %>
|
adapter: <%= ENV.fetch('DATABASE_TYPE') %>
|
||||||
|
encoding: <%= ENV.fetch('DATABASE_ENCODING') %>
|
||||||
|
database: <%= ENV.fetch('DATABASE_NAME') %>
|
||||||
|
host: <%= ENV.fetch('DATABASE_HOST') %>
|
||||||
|
port: <%= ENV.fetch('DATABASE_PORT') %>
|
||||||
|
username: <%= ENV.fetch('DATABASE_USERNAME') %>
|
||||||
|
password: <%= ENV.fetch('DATABASE_PASSWORD') %>
|
||||||
|
|
||||||
|
development:
|
||||||
|
adapter: <%= ENV.fetch('DATABASE_TYPE') %>
|
||||||
|
encoding: <%= ENV.fetch('DATABASE_ENCODING') %>
|
||||||
|
database: <%= ENV.fetch('DATABASE_NAME') %>
|
||||||
|
host: <%= ENV.fetch('DATABASE_HOST') %>
|
||||||
|
port: <%= ENV.fetch('DATABASE_PORT') %>
|
||||||
|
username: <%= ENV.fetch('DATABASE_USERNAME') %>
|
||||||
|
password: <%= ENV.fetch('DATABASE_PASSWORD') %>
|
||||||
|
|
||||||
|
production:
|
||||||
|
adapter: <%= ENV.fetch('DATABASE_TYPE') %>
|
||||||
|
encoding: <%= ENV.fetch('DATABASE_ENCODING') %>
|
||||||
database: <%= ENV.fetch('DATABASE_NAME') %>
|
database: <%= ENV.fetch('DATABASE_NAME') %>
|
||||||
host: <%= ENV.fetch('DATABASE_HOST') %>
|
host: <%= ENV.fetch('DATABASE_HOST') %>
|
||||||
port: <%= ENV.fetch('DATABASE_PORT') %>
|
port: <%= ENV.fetch('DATABASE_PORT') %>
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
development:
|
|
||||||
adapter: mysql2
|
|
||||||
database: tracks
|
|
||||||
# set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# encoding: utf8
|
|
||||||
host: db
|
|
||||||
username: root
|
|
||||||
password:
|
|
||||||
|
|
||||||
test:
|
|
||||||
adapter: mysql2
|
|
||||||
database: tracks_test
|
|
||||||
# set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# encoding: utf8
|
|
||||||
host: db
|
|
||||||
username: root
|
|
||||||
password:
|
|
||||||
|
|
||||||
# Production config is disabled by default
|
|
||||||
#
|
|
||||||
# production:
|
|
||||||
# adapter: mysql2
|
|
||||||
# database: tracks
|
|
||||||
# # set this if you are storing utf8 in your mysql database to handle strings
|
|
||||||
# # like "Réné".Not needed for sqlite. For PostgreSQL use encoding: unicode
|
|
||||||
# # encoding: utf8
|
|
||||||
# host: localhost
|
|
||||||
# username: root
|
|
||||||
# password:
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ en:
|
||||||
user:
|
user:
|
||||||
auth_type: Auth type
|
auth_type: Auth type
|
||||||
display_name: Display name
|
display_name: Display name
|
||||||
|
email: Email address
|
||||||
first_name: First name
|
first_name: First name
|
||||||
last_name: Last name
|
last_name: Last name
|
||||||
login: Login
|
login: Login
|
||||||
|
@ -87,7 +88,7 @@ en:
|
||||||
confirmation: doesn't match confirmation
|
confirmation: doesn't match confirmation
|
||||||
less_than_or_equal_to: must be less than or equal to %{count}
|
less_than_or_equal_to: must be less than or equal to %{count}
|
||||||
blank: can't be blank
|
blank: can't be blank
|
||||||
invalid: "cannot contain the comma (',') character"
|
invalid: "is not valid"
|
||||||
exclusion: is reserved
|
exclusion: is reserved
|
||||||
odd: must be odd
|
odd: must be odd
|
||||||
even: must be even
|
even: must be even
|
||||||
|
@ -400,6 +401,7 @@ en:
|
||||||
import_title: Import data
|
import_title: Import data
|
||||||
preferences: Preferences
|
preferences: Preferences
|
||||||
integrations_: Integrate Tracks
|
integrations_: Integrate Tracks
|
||||||
|
help_page: Help
|
||||||
feeds_title: See a list of available feeds
|
feeds_title: See a list of available feeds
|
||||||
calendar_title: Calendar of due actions
|
calendar_title: Calendar of due actions
|
||||||
completed_tasks: Done
|
completed_tasks: Done
|
||||||
|
@ -819,11 +821,13 @@ en:
|
||||||
authentication_header: Your authentication
|
authentication_header: Your authentication
|
||||||
current_authentication_type: Your authentication type is %{auth_type}
|
current_authentication_type: Your authentication type is %{auth_type}
|
||||||
change_authentication_type: Change your authentication type
|
change_authentication_type: Change your authentication type
|
||||||
|
remove_introduction: You can remove your user account here. Note that this is irreversible and will remove all your data! After removal you will be logged out.
|
||||||
tabs:
|
tabs:
|
||||||
authentication: Authentication
|
authentication: Authentication
|
||||||
tracks_behavior: Tracks behavior
|
tracks_behavior: Tracks behavior
|
||||||
profile: Profile
|
profile: Profile
|
||||||
date_and_time: Date and time
|
date_and_time: Date and time
|
||||||
|
remove_account: Remove account
|
||||||
generate_new_token_confirm: Are you sure? Generating a new token will replace the existing one and break any external usages of this token.
|
generate_new_token_confirm: Are you sure? Generating a new token will replace the existing one and break any external usages of this token.
|
||||||
data:
|
data:
|
||||||
import_successful: Import was successful.
|
import_successful: Import was successful.
|
||||||
|
@ -961,6 +965,7 @@ en:
|
||||||
change_password_prompt: Enter your new password in the fields below and click 'Change password' to replace your current password with your new one.
|
change_password_prompt: Enter your new password in the fields below and click 'Change password' to replace your current password with your new one.
|
||||||
password_confirmation_label: Confirm password
|
password_confirmation_label: Confirm password
|
||||||
destroy_error: There was an error deleting the user %{login}
|
destroy_error: There was an error deleting the user %{login}
|
||||||
|
email_address: Email address
|
||||||
choose_password: Choose password
|
choose_password: Choose password
|
||||||
register_with_cas: With your CAS username
|
register_with_cas: With your CAS username
|
||||||
label_auth_type: Authentication type
|
label_auth_type: Authentication type
|
||||||
|
@ -978,6 +983,8 @@ en:
|
||||||
change_authentication_type: Change authentication type
|
change_authentication_type: Change authentication type
|
||||||
total_notes: Total notes
|
total_notes: Total notes
|
||||||
select_authentication_type: Select your new authentication type and click 'Change authentication type' to replace your current settings.
|
select_authentication_type: Select your new authentication type and click 'Change authentication type' to replace your current settings.
|
||||||
|
approve_tos: I approve the Terms of Service
|
||||||
|
tos_link: read the Terms of Service
|
||||||
feedlist:
|
feedlist:
|
||||||
choose_context: Choose the context you want a feed of
|
choose_context: Choose the context you want a feed of
|
||||||
actions_due_today: Actions due today or earlier
|
actions_due_today: Actions due today or earlier
|
||||||
|
@ -1005,6 +1012,7 @@ en:
|
||||||
login:
|
login:
|
||||||
login_cas: go to the CAS
|
login_cas: go to the CAS
|
||||||
sign_in: Sign in
|
sign_in: Sign in
|
||||||
|
signup_prompt: Want to create an account?
|
||||||
openid_identity_url_not_found: "Sorry, no user by that identity URL exists (%{identity_url})"
|
openid_identity_url_not_found: "Sorry, no user by that identity URL exists (%{identity_url})"
|
||||||
user_no_expiry: Stay logged in
|
user_no_expiry: Stay logged in
|
||||||
cas_no_user_found: "Hello, %{username}! You do not have an account on Tracks."
|
cas_no_user_found: "Hello, %{username}! You do not have an account on Tracks."
|
||||||
|
|
|
@ -25,6 +25,7 @@ Rails.application.routes.draw do
|
||||||
get 'data/xml_export' => 'data#xml_export'
|
get 'data/xml_export' => 'data#xml_export'
|
||||||
get 'data/csv_actions' => 'data#csv_actions'
|
get 'data/csv_actions' => 'data#csv_actions'
|
||||||
|
|
||||||
|
get 'help' => "integrations#help"
|
||||||
get 'integrations' => "integrations#index"
|
get 'integrations' => "integrations#index"
|
||||||
get 'integrations/rest_api' => "integrations#rest_api", :as => 'rest_api_docs'
|
get 'integrations/rest_api' => "integrations#rest_api", :as => 'rest_api_docs'
|
||||||
post 'integrations/cloudmailin' => 'integrations#cloudmailin'
|
post 'integrations/cloudmailin' => 'integrations#cloudmailin'
|
||||||
|
@ -105,7 +106,7 @@ Rails.application.routes.draw do
|
||||||
# This means the controller action needs to parse the extension and set format/content type
|
# This means the controller action needs to parse the extension and set format/content type
|
||||||
# Needed for /todos/tag/first.last.m to work
|
# Needed for /todos/tag/first.last.m to work
|
||||||
get 'todos/tag/:name' => 'todos#tag', :as => :tag, :format => false, :name => /.*/
|
get 'todos/tag/:name' => 'todos#tag', :as => :tag, :format => false, :name => /.*/
|
||||||
|
|
||||||
get 'attachments/:id/:filename' => "todos#attachment"
|
get 'attachments/:id/:filename' => "todos#attachment"
|
||||||
get 'tags.autocomplete' => "todos#tags", :format => 'autocomplete'
|
get 'tags.autocomplete' => "todos#tags", :format => 'autocomplete'
|
||||||
get 'todos/done/tag/:name' => "todos#done_tag", :as => :done_tag
|
get 'todos/done/tag/:name' => "todos#done_tag", :as => :done_tag
|
||||||
|
|
|
@ -25,12 +25,6 @@ secret_token: "secret"
|
||||||
# Set to true when your application is running with https
|
# Set to true when your application is running with https
|
||||||
force_ssl: false
|
force_ssl: false
|
||||||
|
|
||||||
# Configure how static assets (images, stylesheets, etc.) will be served.
|
|
||||||
# The best practice is to have a proxying web server such as Apache or Nginx
|
|
||||||
# serve static assets (images, stylesheets, javascript) for you. Change
|
|
||||||
# this to 'true' if you want Rails to be responsible for serving the static assets
|
|
||||||
# serve_static_assets: false
|
|
||||||
|
|
||||||
# Uncomment if you want to dispatch todos that come from email based on the To:
|
# Uncomment if you want to dispatch todos that come from email based on the To:
|
||||||
# address rather than the From: address.
|
# address rather than the From: address.
|
||||||
# email_dispatch: 'to'
|
# email_dispatch: 'to'
|
||||||
|
@ -48,6 +42,9 @@ force_ssl: false
|
||||||
# Set to true to allow anyone to sign up for a username.
|
# Set to true to allow anyone to sign up for a username.
|
||||||
open_signups: false
|
open_signups: false
|
||||||
|
|
||||||
|
# Set to require TOS approval on signup.
|
||||||
|
#tos_link: "https://www.example.com"
|
||||||
|
|
||||||
# When integrating your tracks instance with http://cloudmailin.com/ by using
|
# When integrating your tracks instance with http://cloudmailin.com/ by using
|
||||||
# the /integrations/cloudmailin URL, this value is the cloudmailin-secret for
|
# the /integrations/cloudmailin URL, this value is the cloudmailin-secret for
|
||||||
# verifying the authenticity of the request.
|
# verifying the authenticity of the request.
|
||||||
|
|
|
@ -28,12 +28,6 @@ secret_token: "change-me"
|
||||||
# Set to true when your application is running with https
|
# Set to true when your application is running with https
|
||||||
force_ssl: false
|
force_ssl: false
|
||||||
|
|
||||||
# Configure how static assets (images, stylesheets, etc.) will be served.
|
|
||||||
# The best practice is to have a proxying web server such as Apache or Nginx
|
|
||||||
# serve static assets (images, stylesheets, javascript) for you. Change
|
|
||||||
# this to 'true' if you want Rails to be responsible for serving the static assets
|
|
||||||
# serve_static_assets: false
|
|
||||||
|
|
||||||
# Uncomment if you want to dispatch todos that come from email based on the To:
|
# Uncomment if you want to dispatch todos that come from email based on the To:
|
||||||
# address rather than the From: address.
|
# address rather than the From: address.
|
||||||
# email_dispatch: 'to'
|
# email_dispatch: 'to'
|
||||||
|
@ -54,6 +48,8 @@ force_ssl: false
|
||||||
# Set to true to allow anyone to sign up for a username.
|
# Set to true to allow anyone to sign up for a username.
|
||||||
open_signups: false
|
open_signups: false
|
||||||
|
|
||||||
|
# Set to require TOS approval on signup.
|
||||||
|
#tos_link: "https://www.example.com"
|
||||||
|
|
||||||
# When integrating your tracks instance with http://cloudmailin.com/ by using
|
# When integrating your tracks instance with http://cloudmailin.com/ by using
|
||||||
# the /integrations/cloudmailin URL, this value is the cloudmailin-secret for
|
# the /integrations/cloudmailin URL, this value is the cloudmailin-secret for
|
||||||
|
|
5
db/migrate/20200720151220_add_email_to_user.rb
Normal file
5
db/migrate/20200720151220_add_email_to_user.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddEmailToUser < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :users, :email, :string
|
||||||
|
end
|
||||||
|
end
|
6
db/migrate/20200807175610_add_dates_to_user.rb
Normal file
6
db/migrate/20200807175610_add_dates_to_user.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class AddDatesToUser < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :users, :created_at, :datetime
|
||||||
|
add_column :users, :updated_at, :datetime
|
||||||
|
end
|
||||||
|
end
|
5
db/migrate/20200810123316_add_lastlogin_to_user.rb
Normal file
5
db/migrate/20200810123316_add_lastlogin_to_user.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddLastloginToUser < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :users, :last_login_at, :datetime
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you 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: 2020_01_09_231555) do
|
ActiveRecord::Schema.define(version: 2020_08_10_123316) do
|
||||||
|
|
||||||
create_table "attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
create_table "attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
|
||||||
t.integer "todo_id"
|
t.integer "todo_id"
|
||||||
|
@ -220,6 +220,10 @@ ActiveRecord::Schema.define(version: 2020_01_09_231555) do
|
||||||
t.string "open_id_url"
|
t.string "open_id_url"
|
||||||
t.string "remember_token"
|
t.string "remember_token"
|
||||||
t.datetime "remember_token_expires_at"
|
t.datetime "remember_token_expires_at"
|
||||||
|
t.string "email"
|
||||||
|
t.datetime "created_at"
|
||||||
|
t.datetime "updated_at"
|
||||||
|
t.datetime "last_login_at"
|
||||||
t.index ["login"], name: "index_users_on_login"
|
t.index ["login"], name: "index_users_on_login"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,108 @@
|
||||||
# Installing Tracks
|
# Installing Tracks
|
||||||
|
|
||||||
The following instructions will guide you through the installation of Tracks from source.
|
Tracks can be installed several ways: You can run it through Docker, which is recommended because all requirements have already been taken care of for you, or you can install it on a custom server from source.
|
||||||
|
|
||||||
|
Community-provided instructions for other options and tips for specific environments are available in the Tracks wiki: https://github.com/TracksApp/tracks/wiki/Installation.
|
||||||
|
|
||||||
|
## Docker installation using Docker Compose
|
||||||
|
|
||||||
|
You can easily run Tracks using Docker Compose. This option mounts the repository directly inside the Docker container, making it an optimal solution for developing Tracks. It does, however, also work for normal users.
|
||||||
|
|
||||||
|
1. Make sure you have Docker Compose and Docker properly installed.
|
||||||
|
2. Get the Tracks code base by either downloading the archive file for the latest releast or cloning it from GitHub.
|
||||||
|
3. Create a file to enable the Docker Compose support in Tracks. *Note*: This is not needed or useful for the separate container, only Docker Composer!
|
||||||
|
```
|
||||||
|
$ touch .use-docker
|
||||||
|
```
|
||||||
|
4. On the installation run the following command:
|
||||||
|
```
|
||||||
|
$ ./script/setup
|
||||||
|
```
|
||||||
|
5. Run the server using the following command:
|
||||||
|
```
|
||||||
|
$ ./script/server
|
||||||
|
```
|
||||||
|
6. You should now be able to access Tracks in http://localhost:3000
|
||||||
|
|
||||||
|
## Docker installation using a separate container
|
||||||
|
|
||||||
|
You can also install Tracks without Docker Compose. This allows you to use the official Docker containers and you can use your existing database server instead of having a separate one for Tracks.
|
||||||
|
|
||||||
|
*Note*: For now, you have to first build the image manually before starting the
|
||||||
|
Tracks container. In future there should be an official image in Docker Hub. You can build the image by:
|
||||||
|
|
||||||
|
1. Get the Tracks code base by either downloading the archive file for the latest releast or cloning it from GitHub.
|
||||||
|
2. Run the following command in the Tracks directory to build the image:
|
||||||
|
```
|
||||||
|
$ docker build -t="tracks" .
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Make sure you have Docker properly installed.
|
||||||
|
2. Start a database container with either MySQL or PostgreSQL:
|
||||||
|
```
|
||||||
|
$ docker run -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=password -d postgres
|
||||||
|
$ docker run -p 3306:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=password -d mariadb
|
||||||
|
```
|
||||||
|
3. Create a database and a user for Tracks in the database:
|
||||||
|
```
|
||||||
|
# MySQL
|
||||||
|
$ mysql -u root -p
|
||||||
|
mysql> CREATE DATABASE tracks;
|
||||||
|
mysql> GRANT ALL PRIVILEGES ON tracks.* TO yourmysqluser@localhost IDENTIFIED BY 'password-goes-here' WITH GRANT OPTION;
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
$ sudo -u postgres psql
|
||||||
|
postgres=# CREATE USER tracks WITH ENCRYPTED PASSWORD 'password-goes-here';
|
||||||
|
postgres=# CREATE DATABASE tracks OWNER=tracks;
|
||||||
|
```
|
||||||
|
4. Install the schema
|
||||||
|
```
|
||||||
|
$ docker run --link mariadb:db --rm -t tracks bin/rake db:reset
|
||||||
|
$ docker run --link postgres:db --rm -t tracks bin/rake db:reset
|
||||||
|
```
|
||||||
|
5. Start the Tracks server:
|
||||||
|
```
|
||||||
|
$ docker run -p 3000:3000 --name tracks --link mariadb:db -t tracks
|
||||||
|
$ docker run -p 3000:3000 --name tracks --link postgres:db -t tracks
|
||||||
|
```
|
||||||
|
6. You should now be able to access Tracks in http://localhost:3000
|
||||||
|
|
||||||
|
## Environmental variables in the Docker image
|
||||||
|
|
||||||
|
You can override database connection details by defining the environment variables in the run command, for example ”-e DATABASE_USERNAME=tracks_dev” or docker-compose.yml, if using Docker Compose.
|
||||||
|
|
||||||
|
|Name |Default |For PostgreSQL |
|
||||||
|
|------------------|-----------|---------------|
|
||||||
|
|DATABASE_NAME |tracks | |
|
||||||
|
|DATABASE_HOST |db | |
|
||||||
|
|DATABASE_PORT |3306 |5432 |
|
||||||
|
|DATABASE_USERNAME |tracks | |
|
||||||
|
|DATABASE_PASSWORD |password | |
|
||||||
|
|DATABASE_TYPE |mysql2 |postgresql |
|
||||||
|
|DATABASE_ENCODING |utf8 |unicode |
|
||||||
|
|RAILS_ENV |production |
|
||||||
|
|
||||||
|
### Override files
|
||||||
|
|
||||||
|
You can override files in the Docker image by using the --volume argument or docker-compose.yml, if using Docker Compose.
|
||||||
|
|
||||||
|
|File |Argument |Replace for production?|
|
||||||
|
|-------------------|---------------------------------------------------------|-----------------------|
|
||||||
|
|config/site.yml |--volume /app/config/site.yml:/home/user/site.yml |Yes |
|
||||||
|
|
||||||
|
## Custom server installation
|
||||||
|
|
||||||
This description is intended for people installing Tracks from scratch. If you would like to upgrade an existing installation, please see the [upgrade documentation](upgrading.md).
|
This description is intended for people installing Tracks from scratch. If you would like to upgrade an existing installation, please see the [upgrade documentation](upgrading.md).
|
||||||
|
|
||||||
For alternative installation options and tips for specific environments, please see [Installation](https://github.com/TracksApp/tracks/wiki/Installation) on the wiki.
|
### Prerequisites
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Tracks has a few software requirements that must be satisfied before installation:
|
Tracks has a few software requirements that must be satisfied before installation:
|
||||||
|
|
||||||
1. **Ruby**. Tracks requires Ruby 2.4 or greater, but is not tested with 2.7.
|
1. **Ruby**. Tracks requires Ruby 2.5 or greater. Most of the testing is done with 2.6.
|
||||||
2. **Bundler**. Tracks requires a recent version of [Bundler](http://bundler.io) to handle the installation of dependencies. Bundler is typically installed by running `gem install bundler`.
|
2. **Bundler**. Tracks requires a recent version of [Bundler](http://bundler.io) to handle the installation of dependencies. Bundler is typically installed by running `gem install bundler`.
|
||||||
3. **Database**. Tracks is tested on [MySQL](http://www.mysql.com/) and [SQLite](http://www.sqlite.org/), but [PostgreSQL](http://www.postgresql.org/) can also be used. Of the three, SQLite requires the least configuration. Whatever your choice, the appropriate database software must be installed.
|
3. **Database**. Tracks is tested on [MySQL](http://www.mysql.com/) and [SQLite](http://www.sqlite.org/), but [PostgreSQL](http://www.postgresql.org/) can also be used. Of the three, SQLite requires the least configuration but is also the least performant and may make it difficult to operate in the future. We recommend either MySQL or PostgreSQL. Whatever your choice, the appropriate database software must be installed.
|
||||||
|
|
||||||
## Get Tracks
|
### Get Tracks
|
||||||
|
|
||||||
There are two methods of downloading Tracks:
|
There are two methods of downloading Tracks:
|
||||||
|
|
||||||
|
@ -27,18 +115,26 @@ There are two methods of downloading Tracks:
|
||||||
git clone https://github.com/TracksApp/tracks.git
|
git clone https://github.com/TracksApp/tracks.git
|
||||||
cd tracks
|
cd tracks
|
||||||
|
|
||||||
## Set up the database
|
### Set up the database
|
||||||
|
|
||||||
*This section only applies if you will be using Tracks with a MySQL database.*
|
*This section doesn't apply if using SQLite.*
|
||||||
|
|
||||||
You need to create a database and database-user to use with Tracks. For this, you can use MySQL Administrator or go into a terminal and issue the following commands:
|
You need to create a database and database-user to use with Tracks. For this, you can use an GUI tool or go into a terminal and issue the following commands:
|
||||||
|
|
||||||
mysql -u root -p
|
#### MySQL
|
||||||
|
|
||||||
|
$ mysql -u root -p
|
||||||
mysql> CREATE DATABASE tracks;
|
mysql> CREATE DATABASE tracks;
|
||||||
mysql> GRANT ALL PRIVILEGES ON tracks.* TO yourmysqluser@localhost \
|
mysql> GRANT ALL PRIVILEGES ON tracks.* TO yourmysqluser@localhost \
|
||||||
IDENTIFIED BY 'password-goes-here' WITH GRANT OPTION;
|
IDENTIFIED BY 'password-goes-here' WITH GRANT OPTION;
|
||||||
|
|
||||||
## Install dependencies
|
#### PostgreSQL
|
||||||
|
|
||||||
|
$ sudo -u postgres psql
|
||||||
|
postgres=# CREATE USER tracks WITH ENCRYPTED PASSWORD 'password-goes-here';
|
||||||
|
postgres=# CREATE DATABASE tracks OWNER=tracks;
|
||||||
|
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
Tracks is built upon a number of Ruby libraries (known as ‘gems’). The Bundler tool makes it easy to install all the gems that Tracks needs, and ensures that they are all the correct versions.
|
Tracks is built upon a number of Ruby libraries (known as ‘gems’). The Bundler tool makes it easy to install all the gems that Tracks needs, and ensures that they are all the correct versions.
|
||||||
|
|
||||||
|
@ -64,10 +160,9 @@ Tracks is built upon a number of Ruby libraries (known as ‘gems’). The Bundl
|
||||||
2. Open the file `config/database.yml` and edit the `production:` section with the details of your database. If you are using MySQL the `adapter:` line should read `adapter: mysql2`, `host: localhost` (in the majority of cases), and your username and password should match those you assigned when you created the database. If you are using SQLite3, you should have only two lines under the production section: `adapter: sqlite3` and `database: db/tracks.db`.
|
2. Open the file `config/database.yml` and edit the `production:` section with the details of your database. If you are using MySQL the `adapter:` line should read `adapter: mysql2`, `host: localhost` (in the majority of cases), and your username and password should match those you assigned when you created the database. If you are using SQLite3, you should have only two lines under the production section: `adapter: sqlite3` and `database: db/tracks.db`.
|
||||||
3. Open the file `config/site.yml`, and read through the settings to make sure that they suit your setup. In most cases, all you need to change are the `secret_token`, the administrator email address (`admin_email`), and the time zone setting. For the time zone setting you can use the command `bundle exec rake time:zones:local` to see all available timezones on your machine
|
3. Open the file `config/site.yml`, and read through the settings to make sure that they suit your setup. In most cases, all you need to change are the `secret_token`, the administrator email address (`admin_email`), and the time zone setting. For the time zone setting you can use the command `bundle exec rake time:zones:local` to see all available timezones on your machine
|
||||||
4. If you are using Windows, you may need to check the ‘shebang’ lines (`#!/usr/bin/env ruby`) of the `/public/dispatch.*` files and all the files in the `/script` directory. They are set to `#!/usr/bin/env ruby` by default. This should work for all Unix based setups (Linux or Mac OS X), but Windows users will probably have to change it to something like `#c:/ruby/bin/ruby` to point to the Ruby binary on your system.
|
4. If you are using Windows, you may need to check the ‘shebang’ lines (`#!/usr/bin/env ruby`) of the `/public/dispatch.*` files and all the files in the `/script` directory. They are set to `#!/usr/bin/env ruby` by default. This should work for all Unix based setups (Linux or Mac OS X), but Windows users will probably have to change it to something like `#c:/ruby/bin/ruby` to point to the Ruby binary on your system.
|
||||||
5. If you intend to deploy Tracks using its included web server, you’ll need to uncomment and change the `serve_static_assets` configuration option to `true` in `config/site.yml` in order for the images, stylesheets, and javascript files to be served correctly.
|
5. If you intend to use Tracks behind a web server or reverse proxy with https enabled, ensure to set `force_ssl` option to `true`.
|
||||||
6. If you intend to use Tracks behind a web server or reverse proxy with https enabled, ensure to set `force_ssl` option to `true`.
|
|
||||||
|
|
||||||
## Populate your database with the Tracks schema
|
### Populate your database with the Tracks schema
|
||||||
|
|
||||||
Open a terminal and change into the root of your Tracks directory. Enter the following command:
|
Open a terminal and change into the root of your Tracks directory. Enter the following command:
|
||||||
|
|
||||||
|
@ -75,24 +170,26 @@ Open a terminal and change into the root of your Tracks directory. Enter the fol
|
||||||
|
|
||||||
This will set up your database with the required structure to hold Tracks’ data.
|
This will set up your database with the required structure to hold Tracks’ data.
|
||||||
|
|
||||||
## Precompile assets
|
### Precompile assets
|
||||||
|
|
||||||
Static assets (images, stylesheets, and javascript) need to be compiled in order for them to work correctly with the new asset pipeline feature in Rails. Precompiling your assets is as simple as running the following command while inside the Tracks root directory:
|
Static assets (images, stylesheets, and javascript) need to be compiled in order for them to work correctly with the new asset pipeline feature in Rails. Precompiling your assets is as simple as running the following command while inside the Tracks root directory:
|
||||||
|
|
||||||
bundle exec rake assets:precompile RAILS_ENV=production
|
bundle exec rake assets:precompile RAILS_ENV=production
|
||||||
|
|
||||||
## Start the server
|
### Start the server
|
||||||
|
|
||||||
While still in the Terminal inside the Tracks root directory, issue the following command:
|
While still in the Terminal inside the Tracks root directory, issue the following command:
|
||||||
|
|
||||||
bundle exec rails server -e production
|
RAILS_SERVE_STATIC_FILES=TRUE bundle exec rails server -e production
|
||||||
|
|
||||||
If all goes well, you should see some text informing you that the server is running: `=> Rails application starting in production on http://localhost:3000`. If you are already running other services on port 3000, you need to select a different port when running the server, using the `-p` option.
|
If all goes well, you should see some text informing you that the server is running: `=> Rails application starting in production on http://localhost:3000`. If you are already running other services on port 3000, you need to select a different port when running the server, using the `-p` option.
|
||||||
|
|
||||||
## Visit Tracks in a browser
|
Optimally you should serve static files using Nginx or Apache, especially in larger production instances. If you do this, you can omit the RAILS_SERVE_STATIC_FILES=TRUE from the start of the command.
|
||||||
|
|
||||||
|
### Visit Tracks in a browser
|
||||||
|
|
||||||
Visit `http://localhost:3000/signup` in a browser (or whatever URL and port was reported when you started the server in the step above) and chose a user name and password for admin user. Once logged in as admin, you can add other (ordinary level) users. If you need to access Tracks from a mobile/cellular phone browser, visit `http://yourdomain.com/mobile/`. This mobile version is a special, lightweight version of Tracks, designed to use on a mobile browser.
|
Visit `http://localhost:3000/signup` in a browser (or whatever URL and port was reported when you started the server in the step above) and chose a user name and password for admin user. Once logged in as admin, you can add other (ordinary level) users. If you need to access Tracks from a mobile/cellular phone browser, visit `http://yourdomain.com/mobile/`. This mobile version is a special, lightweight version of Tracks, designed to use on a mobile browser.
|
||||||
|
|
||||||
## Customise Tracks
|
### Customise Tracks
|
||||||
|
|
||||||
Once logged in, add some Contexts and Projects, and then go ahead and add your actions. You might also want to visit the Preferences page to edit various settings to your liking. Have fun!
|
Once logged in, add some Contexts and Projects, and then go ahead and add your actions. You might also want to visit the Preferences page to edit various settings to your liking. Have fun!
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
# Upgrading Tracks
|
# Upgrading Tracks
|
||||||
|
## Upgrading from Tracks 2.4.2 to 2.5
|
||||||
|
|
||||||
|
* If you're using the Docker Compose environment and want to run the commands in
|
||||||
|
the bin/ directory inside the container from the host system, add a .use-docker
|
||||||
|
file to the root directory. This replaces the old .skip-docker file requirement
|
||||||
|
to favor the more common setup and avoid placing unexpected requirements.
|
||||||
|
|
||||||
|
* The Docker environment has been changed quite a bit. However, it should work
|
||||||
|
at least as before for the usual needs.
|
||||||
|
|
||||||
## Upgrading from Tracks 2.3 to 2.4.2
|
## Upgrading from Tracks 2.3 to 2.4.2
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,16 @@ services:
|
||||||
- db-data:/var/lib/mysql
|
- db-data:/var/lib/mysql
|
||||||
web:
|
web:
|
||||||
build: .
|
build: .
|
||||||
|
environment:
|
||||||
|
# These are set in script/ci-build, so we need to pass-thru them.
|
||||||
|
RAILS_ENV: $RAILS_ENV
|
||||||
|
DATABASE_NAME: $DATABASE_NAME
|
||||||
|
DATABASE_USERNAME: root
|
||||||
|
DATABASE_PASSWORD_EMPTY: 1
|
||||||
volumes:
|
volumes:
|
||||||
- ${VOLUME:-.:/app}
|
- ${VOLUME:-.}:/app:Z
|
||||||
|
- ${VOLUME:-.}/config/database.docker.yml:/app/config/database.yml:Z
|
||||||
|
- ${VOLUME:-.}/config/site.docker.yml:/app/config/site.yml:Z
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
20
docker-entrypoint.sh
Executable file
20
docker-entrypoint.sh
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export RAILS_ENV=${RAILS_ENV:-production}
|
||||||
|
export DATABASE_NAME=${DATABASE_NAME:-tracks}
|
||||||
|
export DATABASE_HOST=${DATABASE_HOST:-db}
|
||||||
|
export DATABASE_PORT=${DATABASE_PORT:-3306}
|
||||||
|
export DATABASE_USERNAME=${DATABASE_USERNAME:-tracks}
|
||||||
|
if [ "$DATABASE_PASSWORD_EMPTY" != 1 ];
|
||||||
|
then
|
||||||
|
export DATABASE_PASSWORD=${DATABASE_PASSWORD:-password}
|
||||||
|
else
|
||||||
|
export DATABASE_PASSWORD=""
|
||||||
|
fi
|
||||||
|
export DATABASE_TYPE=${DATABASE_TYPE:-mysql2}
|
||||||
|
export DATABASE_ENCODING=${DATABASE_ENCODING:-utf8}
|
||||||
|
|
||||||
|
export RAILS_SERVE_STATIC_FILES=TRUE
|
||||||
|
export RAILS_LOG_TO_STDOUT=TRUE
|
||||||
|
|
||||||
|
exec "$@"
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
rails db:migrate
|
|
||||||
rails server -b 0.0.0.0
|
|
|
@ -222,6 +222,7 @@ private
|
||||||
def redirect_to_login
|
def redirect_to_login
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to login_path }
|
format.html { redirect_to login_path }
|
||||||
|
format.js { render js: "redirect_to('" + login_path + "')" }
|
||||||
format.m { redirect_to login_path(:format => 'm') }
|
format.m { redirect_to login_path(:format => 'm') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
14
script/bootstrap
Executable file
14
script/bootstrap
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/bootstrap: Resolve all dependencies that the application requires to
|
||||||
|
# run.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
|
|
||||||
|
echo "==> Building Docker image…"
|
||||||
|
$docker_compose build
|
||||||
|
|
||||||
|
echo "==> Building assets…"
|
||||||
|
bin/rake assets:precompile
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
docker_compose="docker-compose --file docker-compose.yml"
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
|
@ -12,14 +13,10 @@ function die() {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
export RAILS_ENV=test
|
export RAILS_ENV=test
|
||||||
export TRACKS_DB=tracks_test
|
export DATABASE_NAME=tracks_test
|
||||||
|
|
||||||
# Put a config/site.yml file in place since it's needed for operation
|
|
||||||
cp config/site.yml.tmpl config/site.yml
|
|
||||||
|
|
||||||
$docker_compose build
|
$docker_compose build
|
||||||
$docker_compose up -d
|
$docker_compose up -d
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
appdir=$(cd $(dirname "$0")/.. && pwd)
|
|
||||||
[ -f /etc/app-env ] || exec "$appdir/script/docker-environment" $0 $@
|
|
||||||
|
|
||||||
export RAILS_ENV='development'
|
export RAILS_ENV='development'
|
||||||
bin/rails console
|
bin/rails console
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Run a command in the app's environment
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Find our app dir and just run the command in we're in the container since the
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
# container is built with an /etc/app-env file inside of it.
|
|
||||||
appdir=$(cd $(dirname "$0")/.. && pwd)
|
|
||||||
[ -f /etc/app-env ] && exec "$@"
|
|
||||||
|
|
||||||
# Otherwise, run docker compose to run our command in the container
|
# Find our app dir
|
||||||
|
appdir=$(cd $(dirname "$0")/.. && pwd)
|
||||||
|
|
||||||
|
# Check if we've been told to run the command in Docker Composer.
|
||||||
cmd="$@"; [ "$#" -eq 0 ] && cmd=bash
|
cmd="$@"; [ "$#" -eq 0 ] && cmd=bash
|
||||||
export VOLUME="$appdir:/app"
|
export VOLUME="$appdir"
|
||||||
image=${DOCKER_IMAGE:=web}
|
image=${DOCKER_IMAGE:=web}
|
||||||
|
|
||||||
port_publish=""; [ "${BIND_DOCKER_SERVICE_PORTS:-}" = 1 ] && port_publish="--service-ports"
|
port_publish=""; [ "${BIND_DOCKER_SERVICE_PORTS:-}" = 1 ] && port_publish="--service-ports"
|
||||||
exec docker-compose run $port_publish --rm $image $cmd
|
exec $docker_compose run $port_publish --rm $image $cmd
|
||||||
|
|
18
script/setup
Executable file
18
script/setup
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/setup: Set up application for the first time after cloning, or set it
|
||||||
|
# back to the initial first unused state.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
|
|
||||||
|
script/bootstrap
|
||||||
|
|
||||||
|
script/poll-for-db
|
||||||
|
|
||||||
|
echo "==> Setting up DB…"
|
||||||
|
# reset database to a fresh state.
|
||||||
|
bin/rake db:reset
|
||||||
|
|
||||||
|
echo "==> App is now ready to go!"
|
47
script/test
Executable file
47
script/test
Executable file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# script/test: Run test suite for application. Optionally pass in a path to an
|
||||||
|
# individual test file to run a single test.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
$docker_compose down
|
||||||
|
}
|
||||||
|
|
||||||
|
function die() {
|
||||||
|
echo $@
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
script/poll-for-db
|
||||||
|
|
||||||
|
if [ "$RAILS_ENV" = "test" ] || [ "$RACK_ENV" = "test" ]; then
|
||||||
|
# if executed and the environment is already set to `test`, then we want a
|
||||||
|
# clean from scratch application. This almost always means a ci environment,
|
||||||
|
# since we set the environment to `test` directly in `script/cibuild`.
|
||||||
|
script/setup
|
||||||
|
else
|
||||||
|
# if the environment isn't set to `test`, set it to `test` and update the
|
||||||
|
# application to ensure all dependencies are met as well as any other things
|
||||||
|
# that need to be up to date, like db migrations. The environment not having
|
||||||
|
# already been set to `test` almost always means this is being called on its
|
||||||
|
# own from a `development` environment.
|
||||||
|
export RAILS_ENV="test" RACK_ENV="test"
|
||||||
|
|
||||||
|
script/update
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Running tests…"
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
# pass arguments to test call. This is useful for calling a single test.
|
||||||
|
$docker_compose run web bin/rake test "$1"
|
||||||
|
else
|
||||||
|
$docker_compose run web bin/rake test
|
||||||
|
fi
|
||||||
|
|
13
script/update
Executable file
13
script/update
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/update: Update application to run for its current checkout.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker_compose="docker-compose --file docker-compose.yml"
|
||||||
|
|
||||||
|
script/bootstrap
|
||||||
|
|
||||||
|
echo "==> Updating db…"
|
||||||
|
# run all database migrations to ensure everything is up to date.
|
||||||
|
$docker_compose run web bin/rake db:migrate
|
|
@ -18,7 +18,7 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
get :index
|
get :index
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_equal "TRACKS::Manage Users", assigns['page_title']
|
assert_equal "TRACKS::Manage Users", assigns['page_title']
|
||||||
assert_equal 4, assigns['total_users']
|
assert_equal 5, assigns['total_users']
|
||||||
assert_equal users_url, session['return-to']
|
assert_equal users_url, session['return-to']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
assert_equal assigns['users'],[User.where(:login => 'jane').first]
|
assert_equal assigns['users'],[User.where(:login => 'jane').first]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_destroy_user
|
def test_destroy_user_as_admin
|
||||||
login_as :admin_user
|
login_as :admin_user
|
||||||
@no_users_before = User.count
|
@no_users_before = User.count
|
||||||
user_id = users(:ldap_user).id
|
user_id = users(:ldap_user).id
|
||||||
|
@ -44,8 +44,16 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
assert_equal @no_users_before-1, User.count
|
assert_equal @no_users_before-1, User.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_destroy_user_as_user
|
||||||
|
login_as :other_user
|
||||||
|
@no_users_before = User.count
|
||||||
|
user_id = users(:other_user).id
|
||||||
|
post :destroy, xhr: true, params: { :id => user_id.to_param }
|
||||||
|
assert_equal @no_users_before-1, User.count
|
||||||
|
end
|
||||||
|
|
||||||
def test_update_password_successful
|
def test_update_password_successful
|
||||||
get :change_password, params: { :id => users(:admin_user).id }
|
get :change_password, params: { :id => users(:admin_user).id }
|
||||||
# should fail because no login
|
# should fail because no login
|
||||||
assert_redirected_to login_path
|
assert_redirected_to login_path
|
||||||
login_as :admin_user
|
login_as :admin_user
|
||||||
|
|
12
test/fixtures/users.yml
vendored
12
test/fixtures/users.yml
vendored
|
@ -48,3 +48,15 @@ ldap_user:
|
||||||
first_name: International
|
first_name: International
|
||||||
last_name: Harvester
|
last_name: Harvester
|
||||||
auth_type: CAS
|
auth_type: CAS
|
||||||
|
|
||||||
|
other_user_email:
|
||||||
|
id: 6
|
||||||
|
login: joe
|
||||||
|
crypted_password: <%= BCrypt::Password.create("open") %>
|
||||||
|
token: <%= Digest::SHA1.hexdigest("joeSun Feb 19 14:42:45 GMT 20060.408173979260027") %>
|
||||||
|
is_admin: false
|
||||||
|
first_name: Jane
|
||||||
|
last_name: Doe
|
||||||
|
email: joe@example.org
|
||||||
|
auth_type: database
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ require 'support/stub_site_config_helper'
|
||||||
|
|
||||||
class StoriesTest < ActionDispatch::IntegrationTest
|
class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
include StubSiteConfigHelper
|
include StubSiteConfigHelper
|
||||||
|
|
||||||
# ####################################################
|
# ####################################################
|
||||||
# Testing login and signup by different kinds of users
|
# Testing login and signup by different kinds of users
|
||||||
# ####################################################
|
# ####################################################
|
||||||
|
@ -11,10 +11,11 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
admin = new_session_as(:admin_user,"abracadabra")
|
admin = new_session_as(:admin_user,"abracadabra")
|
||||||
admin.goes_to_signup
|
admin.goes_to_signup
|
||||||
admin.signs_up_with(:user => {:login => "newbie",
|
admin.signs_up_with(:user => {:login => "newbie",
|
||||||
|
:email => "test.person@example.org",
|
||||||
:password => "newbiepass",
|
:password => "newbiepass",
|
||||||
:password_confirmation => "newbiepass"})
|
:password_confirmation => "newbiepass"})
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_signup_new_user_by_nonadmin
|
def test_signup_new_user_by_nonadmin
|
||||||
stub_site_config do
|
stub_site_config do
|
||||||
SITE_CONFIG['open_signups'] = false
|
SITE_CONFIG['open_signups'] = false
|
||||||
|
@ -22,7 +23,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
other_user.goes_to_signup_as_nonadmin
|
other_user.goes_to_signup_as_nonadmin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_open_signup_new_user
|
def test_open_signup_new_user
|
||||||
stub_site_config do
|
stub_site_config do
|
||||||
SITE_CONFIG['open_signups'] = true
|
SITE_CONFIG['open_signups'] = true
|
||||||
|
@ -30,6 +31,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "users/new"
|
assert_template "users/new"
|
||||||
post "/users", params: { :user => {:login => "newbie",
|
post "/users", params: { :user => {:login => "newbie",
|
||||||
|
:email => "test.person@example.org",
|
||||||
:password => "newbiepass",
|
:password => "newbiepass",
|
||||||
:password_confirmation => "newbiepass"} }
|
:password_confirmation => "newbiepass"} }
|
||||||
assert_response :redirect
|
assert_response :redirect
|
||||||
|
@ -37,8 +39,8 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "todos/index"
|
assert_template "todos/index"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
module CustomAssertions
|
module CustomAssertions
|
||||||
|
@ -67,7 +69,7 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "users/new"
|
assert_template "users/new"
|
||||||
end
|
end
|
||||||
|
|
||||||
def goes_to_signup_as_nonadmin
|
def goes_to_signup_as_nonadmin
|
||||||
get "/signup"
|
get "/signup"
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
@ -81,7 +83,6 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template "todos/index"
|
assert_template "todos/index"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_session_as(user,plainpass)
|
def new_session_as(user,plainpass)
|
||||||
|
@ -92,5 +93,4 @@ class StoriesTest < ActionDispatch::IntegrationTest
|
||||||
yield sess if block_given?
|
yield sess if block_given?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
|
|
||||||
@@foobar_postdata = "<user><login>foo</login><password>bar</password></user>"
|
@@foobar_postdata = "<user><login>foo</login><password>bar</password></user>"
|
||||||
|
@@barfoo_postdata = "<user><login>bar</login><email>barfoo@example.org</email><password>foo</password></user>"
|
||||||
@@johnny_postdata = "<user><login>johnny</login><password>barracuda</password></user>"
|
@@johnny_postdata = "<user><login>johnny</login><password>barracuda</password></user>"
|
||||||
|
@@barracuda_postdata = "<user><login>barracuda</login><email>barracuda@example.org</email><password>johnny</password></user>"
|
||||||
|
|
||||||
def test_fails_with_401_if_not_authorized_user
|
def test_fails_with_401_if_not_authorized_user
|
||||||
authenticated_post_xml_to_user_create @@foobar_postdata, 'nobody', 'nohow'
|
authenticated_post_xml_to_user_create @@foobar_postdata, 'nobody', 'nohow'
|
||||||
assert_401_unauthorized_admin
|
assert_401_unauthorized_admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fails_with_401_if_not_admin_user
|
def test_fails_with_401_if_not_admin_user
|
||||||
authenticated_post_xml_to_user_create @@foobar_postdata, users(:other_user).login, 'sesame'
|
authenticated_post_xml_to_user_create @@foobar_postdata, users(:other_user).login, 'sesame'
|
||||||
assert_401_unauthorized_admin
|
assert_401_unauthorized_admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_type_must_be_xml
|
def test_content_type_must_be_xml
|
||||||
authenticated_post_xml_to_user_create @@foobar_postdata, users(:admin_user).login, 'abracadabra', {'CONTENT_TYPE' => "application/x-www-form-urlencoded"}
|
authenticated_post_xml_to_user_create @@foobar_postdata, users(:admin_user).login, 'abracadabra', {'CONTENT_TYPE' => "application/x-www-form-urlencoded"}
|
||||||
assert_response 400, "Expected response 400"
|
assert_response 400, "Expected response 400"
|
||||||
|
@ -25,12 +27,12 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
# authenticated_post_xml_to_user_create "<foo></bar>"
|
# authenticated_post_xml_to_user_create "<foo></bar>"
|
||||||
# assert_equal 500, @integration_session.status
|
# assert_equal 500, @integration_session.status
|
||||||
# end
|
# end
|
||||||
|
|
||||||
def test_fails_with_invalid_xml_format2
|
def test_fails_with_invalid_xml_format2
|
||||||
authenticated_post_xml_to_user_create "<username>foo</username>"
|
authenticated_post_xml_to_user_create "<username>foo</username>"
|
||||||
assert_response_and_body 400, "Expected post format is valid xml like so: <user><login>username</login><password>abc123</password></user>."
|
assert_response_and_body 400, "Expected post format is valid xml like so: <user><login>username</login><password>abc123</password></user>."
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_xml_simple_param_parsing
|
def test_xml_simple_param_parsing
|
||||||
authenticated_post_xml_to_user_create
|
authenticated_post_xml_to_user_create
|
||||||
assert @controller.params.has_key?(:user)
|
assert @controller.params.has_key?(:user)
|
||||||
|
@ -39,18 +41,18 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
assert_equal 'foo', @controller.params['user'][:login]
|
assert_equal 'foo', @controller.params['user'][:login]
|
||||||
assert_equal 'bar', @controller.params['user'][:password]
|
assert_equal 'bar', @controller.params['user'][:password]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fails_with_too_short_password
|
def test_fails_with_too_short_password
|
||||||
authenticated_post_xml_to_user_create
|
authenticated_post_xml_to_user_create
|
||||||
assert_responses_with_error "Password is too short (minimum is 5 characters"
|
assert_responses_with_error "Password is too short (minimum is 5 characters"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fails_with_nonunique_login
|
def test_fails_with_nonunique_login
|
||||||
existing_login = users(:other_user).login
|
existing_login = users(:other_user).login
|
||||||
authenticated_post_xml_to_user_create "<user><login>#{existing_login}</login><password>barracuda</password></user>"
|
authenticated_post_xml_to_user_create "<user><login>#{existing_login}</login><password>barracuda</password></user>"
|
||||||
assert_responses_with_error "Login has already been taken"
|
assert_responses_with_error "Login has already been taken"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_creates_new_user
|
def test_creates_new_user
|
||||||
assert_difference 'User.count' do
|
assert_difference 'User.count' do
|
||||||
authenticated_post_xml_to_user_create @@johnny_postdata
|
authenticated_post_xml_to_user_create @@johnny_postdata
|
||||||
|
@ -61,16 +63,27 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
johnny2 = User.authenticate('johnny','barracuda')
|
johnny2 = User.authenticate('johnny','barracuda')
|
||||||
assert_not_nil johnny2, "expected user johnny to be authenticated"
|
assert_not_nil johnny2, "expected user johnny to be authenticated"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_creates_new_user
|
||||||
|
assert_difference 'User.count' do
|
||||||
|
authenticated_post_xml_to_user_create @@barracuda_postdata
|
||||||
|
assert_response_and_body 200, "User created."
|
||||||
|
end
|
||||||
|
barracuda1 = User.where(:login => 'barracuda').first
|
||||||
|
assert_not_nil barracuda1, "expected user barracuda to be created"
|
||||||
|
barracuda2 = User.authenticate('barracuda','johnny')
|
||||||
|
assert_not_nil barracuda2, "expected user barracuda to be authenticated"
|
||||||
|
end
|
||||||
|
|
||||||
def test_fails_with_get_verb
|
def test_fails_with_get_verb
|
||||||
authenticated_get_xml "/users.xml", users(:admin_user).login, 'abracadabra', {}
|
authenticated_get_xml "/users.xml", users(:admin_user).login, 'abracadabra', {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_get_users_as_xml
|
def test_get_users_as_xml
|
||||||
get '/users.xml', params: {}, headers: basic_auth_headers()
|
get '/users.xml', params: {}, headers: basic_auth_headers()
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_select 'users' do
|
assert_select 'users' do
|
||||||
assert_select 'user', count: 4
|
assert_select 'user', count: 5
|
||||||
end
|
end
|
||||||
assert_select 'password', false
|
assert_select 'password', false
|
||||||
end
|
end
|
||||||
|
@ -81,7 +94,15 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
assert_select 'user'
|
assert_select 'user'
|
||||||
assert_select 'password', false
|
assert_select 'password', false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_get_email_user_as_xml
|
||||||
|
get "/users/#{users(:other_user_email).id}.xml", params: {}, headers: basic_auth_headers()
|
||||||
|
assert_response :success
|
||||||
|
assert_select 'user'
|
||||||
|
assert_select 'email'
|
||||||
|
assert_select 'password', false
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def basic_auth_headers(username = users(:admin_user).login, password = 'abracadabra')
|
def basic_auth_headers(username = users(:admin_user).login, password = 'abracadabra')
|
||||||
|
@ -91,4 +112,8 @@ class UsersXmlApiTest < ActionDispatch::IntegrationTest
|
||||||
def authenticated_post_xml_to_user_create(postdata = @@foobar_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
|
def authenticated_post_xml_to_user_create(postdata = @@foobar_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
|
||||||
authenticated_post_xml "/users.xml", user, password, postdata, headers
|
authenticated_post_xml "/users.xml", user, password, postdata, headers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def authenticated_post_xml_to_user_create_with_email(postdata = @@barfoo_postdata, user = users(:admin_user).login, password = 'abracadabra', headers = {})
|
||||||
|
authenticated_post_xml "/users.xml", user, password, postdata, headers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -89,6 +89,19 @@ class UserTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_validate_correct_email
|
||||||
|
assert_difference 'User.count' do
|
||||||
|
create_user :email=> 'testi@example.org'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_validate_email_format
|
||||||
|
assert_no_difference 'User.count' do
|
||||||
|
u = create_user :email=> 'test'
|
||||||
|
assert_equal ["is not valid"], u.errors[:email]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_display_name_with_first_and_last_name_set
|
def test_display_name_with_first_and_last_name_set
|
||||||
@other_user.first_name = "Jane"
|
@other_user.first_name = "Jane"
|
||||||
@other_user.last_name = "Doe"
|
@other_user.last_name = "Doe"
|
||||||
|
|
|
@ -140,7 +140,7 @@ class ActionDispatch::IntegrationTest
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_401_unauthorized_admin
|
def assert_401_unauthorized_admin
|
||||||
assert_response_and_body 401, "401 Unauthorized: Only admin users are allowed access to this function."
|
assert_response_and_body 401, "401 Unauthorized: Only administrative users are allowed access to this function."
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_responses_with_error(error_msg)
|
def assert_responses_with_error(error_msg)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue