snapuser 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +37 -0
- data/app/controllers/admin/users_controller.rb +46 -0
- data/app/controllers/sessions_controller.rb +29 -0
- data/app/controllers/users_controller.rb +28 -0
- data/app/helpers/sessions_helper.rb +84 -0
- data/app/models/user.rb +20 -0
- data/app/views/admin/users/_form.html.erb +31 -0
- data/app/views/admin/users/edit.html.erb +3 -0
- data/app/views/admin/users/index.html.erb +5 -0
- data/app/views/admin/users/new.html.erb +3 -0
- data/app/views/sessions/new.html.erb +16 -0
- data/app/views/users/_form.html.erb +25 -0
- data/app/views/users/edit.html.erb +3 -0
- data/app/views/users/profile.html.erb +20 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20150415193853_create_users.rb +13 -0
- data/lib/snapuser/engine.rb +13 -0
- data/lib/snapuser/version.rb +3 -0
- data/lib/snapuser.rb +4 -0
- data/lib/tasks/snapuser_tasks.rake +4 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b38f377cee7d956fe990c3e698a13f18c165a1f7
|
4
|
+
data.tar.gz: 823c7af07d505b94daa27189ebf28f026bff394e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 46fa4257ef80d04818989d8cf4921eb8a25a3ae406d3b29552b2e59149ea550b179c91dc4c9eead8d52740773c26d55c80ce872842f250524ec16803a3535ea2
|
7
|
+
data.tar.gz: 8c8b95b9c5c481a066d46ce98a4d16c0a0bc6572411562f62e20c8d02a1c32ebae421e70ba265e64dbd9faf2c38ecbbf8fa42d2f820528a4945dbe0c6adc3166
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 khcr
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Snapuser'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task default: :test
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Admin::UsersController < ApplicationController
|
2
|
+
before_action { |c| c.authorize_level(1) }
|
3
|
+
layout 'admin'
|
4
|
+
|
5
|
+
def index
|
6
|
+
@table = Table.new(self, User)
|
7
|
+
@table.respond
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
@user = User.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@user = User.new(user_params)
|
16
|
+
if @user.save
|
17
|
+
redirect_to admin_users_path, success: t('user.admin.new.success')
|
18
|
+
else
|
19
|
+
render 'new'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit
|
24
|
+
@user = User.find(params[:id])
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
@user = User.find(params[:id])
|
29
|
+
if @user.update_attributes(user_params)
|
30
|
+
redirect_to admin_users_path, success: t('user.admin.edit.success')
|
31
|
+
else
|
32
|
+
render 'edit'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy
|
37
|
+
User.find(params[:id]).destroy
|
38
|
+
redirect_to admin_activities_path, success: t('user.admin.destroy.success')
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def user_params
|
44
|
+
params.require(:user).permit(:name, :level, :password, :password_confirmation)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class SessionsController < ApplicationController
|
2
|
+
before_action :connected?, except: :destroy
|
3
|
+
|
4
|
+
def new
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
@user = User.where("lower(name) = ?", params[:session][:name].strip.downcase).first
|
9
|
+
if @user && @user.authenticate(params[:session][:password])
|
10
|
+
params[:session][:remember_me] == '1' ? sign_in_permanent(@user) : sign_in(@user)
|
11
|
+
redirect_back_or profile_path, success: t('session.new.success')
|
12
|
+
else
|
13
|
+
flash.now[:error] = t('session.new.error')
|
14
|
+
render 'new'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def destroy
|
19
|
+
sign_out
|
20
|
+
redirect_to root_path, success: t('session.destroy.success')
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def connected?
|
26
|
+
redirect_to profile_path unless current_user.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
before_action except: [:profile] { |c| c.authorize_level(2) }
|
3
|
+
before_action only: [:profile] { |c| c.authorize_level(4) }
|
4
|
+
layout 'admin'
|
5
|
+
|
6
|
+
def profile
|
7
|
+
end
|
8
|
+
|
9
|
+
def edit
|
10
|
+
@user = current_user
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
@user = current_user
|
15
|
+
if @user.update_attributes(user_params)
|
16
|
+
sign_in @user
|
17
|
+
redirect_to profile_path, success: t('user.edit.success')
|
18
|
+
else
|
19
|
+
render 'new'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def user_params
|
26
|
+
params.require(:user).permit(:name, :password, :password_confirmation)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module SessionsHelper
|
2
|
+
|
3
|
+
# Sign in a user with a cookie (remove on browser close)
|
4
|
+
#
|
5
|
+
# * *Args* :
|
6
|
+
# - a user to sign in
|
7
|
+
# * *Returns* :
|
8
|
+
#
|
9
|
+
def sign_in(user)
|
10
|
+
cookies[:remember_token] = user.remember_token
|
11
|
+
self.current_user = user
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sign in a user with a cookie (remove after 2 months)
|
15
|
+
#
|
16
|
+
# * *Args* :
|
17
|
+
# - a user to sign in
|
18
|
+
# * *Returns* :
|
19
|
+
#
|
20
|
+
def sign_in_permanent(user)
|
21
|
+
cookies[:remember_token] = { value: user.remember_token, expires: Time.now + 2592000 }
|
22
|
+
self.current_user = user
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_user=(user)
|
26
|
+
@current_user = user
|
27
|
+
end
|
28
|
+
|
29
|
+
# Provid the user currently signed in.
|
30
|
+
#
|
31
|
+
# * *Returns* :
|
32
|
+
# - the user currently signed in
|
33
|
+
def current_user
|
34
|
+
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Check if there is a user signed in.
|
39
|
+
#
|
40
|
+
# * *Returns* :
|
41
|
+
# - true or false
|
42
|
+
def signed_in?
|
43
|
+
!current_user.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
# Sign out a user by removing the cookie.
|
47
|
+
def sign_out
|
48
|
+
self.current_user = nil
|
49
|
+
cookies.delete(:remember_token)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Store the current url in session's variable
|
53
|
+
#
|
54
|
+
# * *Args* :
|
55
|
+
#
|
56
|
+
# * *Returns* :
|
57
|
+
#
|
58
|
+
def store_location
|
59
|
+
cookies[:return_to] = { value: request.fullpath, expires: 1.minute.from_now }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Redirect the user to the stored url or the default one provided
|
63
|
+
#
|
64
|
+
# * *Args* :
|
65
|
+
# - default path to redirect to
|
66
|
+
# * *Returns* :
|
67
|
+
#
|
68
|
+
def redirect_back_or(default, message = nil)
|
69
|
+
redirect_to(cookies[:return_to] || default, message)
|
70
|
+
session.delete(:return_to)
|
71
|
+
end
|
72
|
+
|
73
|
+
def authorize_level?(level = 3)
|
74
|
+
current_user && current_user.level <= level
|
75
|
+
end
|
76
|
+
|
77
|
+
def authorize_level(level = 3)
|
78
|
+
unless authorize_level?(level)
|
79
|
+
store_location
|
80
|
+
redirect_to login_path, error: "Pas autorisé"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
|
3
|
+
has_secure_password({ validations: false })
|
4
|
+
|
5
|
+
before_save :create_remember_token
|
6
|
+
|
7
|
+
validates :name, presence: true, length: { maximum: 15 }, uniqueness: { case_sensitive: false }
|
8
|
+
validates :password, presence: true, length: { minimum: 5 }, confirmation: true, :unless => lambda { |v| v.validate_password? }
|
9
|
+
validates :level, presence: true
|
10
|
+
|
11
|
+
def validate_password?
|
12
|
+
password.blank? && password_confirmation.blank? && !self.new_record?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def create_remember_token
|
18
|
+
self.remember_token = SecureRandom.urlsafe_base64
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<%= form_for [:admin, @user] do |f| %>
|
2
|
+
|
3
|
+
<%= render 'error_messages', object: f.object %>
|
4
|
+
<ul class="form col2">
|
5
|
+
<li>
|
6
|
+
<%= f.label :name %>
|
7
|
+
<%= f.text_field :name %>
|
8
|
+
</li>
|
9
|
+
<li>
|
10
|
+
<%= f.label :password %>
|
11
|
+
<%= f.password_field :password %>
|
12
|
+
</li>
|
13
|
+
</ul>
|
14
|
+
<ul class="form col2">
|
15
|
+
<li>
|
16
|
+
<%= f.label :password_confirmation %>
|
17
|
+
<%= f.password_field :password_confirmation %>
|
18
|
+
</li>
|
19
|
+
<li>
|
20
|
+
<%= f.label :level %>
|
21
|
+
<%= f.select :level, {"superadmin" => "1", "admin" => "2", "leader" => "3", "uploader" => "4", "member" => "5"} %>
|
22
|
+
</li>
|
23
|
+
</ul>
|
24
|
+
<div id="clear"></div>
|
25
|
+
|
26
|
+
<ul class="center">
|
27
|
+
<li>
|
28
|
+
<%= f.submit %>
|
29
|
+
</li>
|
30
|
+
</ul>
|
31
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :id, "login" %>
|
2
|
+
|
3
|
+
<%= form_for :session, url: sessions_path do |f| %>
|
4
|
+
|
5
|
+
<%= f.label :name %>
|
6
|
+
<%= f.text_field :name %>
|
7
|
+
|
8
|
+
<%= f.label :password %>
|
9
|
+
<%= f.password_field :password %>
|
10
|
+
<div class="rem">
|
11
|
+
<%= f.label :remember_me %>
|
12
|
+
<%= f.check_box :remember_me %>
|
13
|
+
</div>
|
14
|
+
<%= f.submit %>
|
15
|
+
|
16
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%= form_for @user, url: user_update_path do |f| %>
|
2
|
+
|
3
|
+
<%= render 'error_messages', object: f.object %>
|
4
|
+
<ul class="form">
|
5
|
+
<li>
|
6
|
+
<%= f.label :name %>
|
7
|
+
<%= f.text_field :name %>
|
8
|
+
</li>
|
9
|
+
<li>
|
10
|
+
<%= f.label :password %>
|
11
|
+
<%= f.password_field :password %>
|
12
|
+
</li>
|
13
|
+
<li>
|
14
|
+
<%= f.label :password_confirmation %>
|
15
|
+
<%= f.password_field :password_confirmation %>
|
16
|
+
</li>
|
17
|
+
<ul>
|
18
|
+
<div id="clear"></div>
|
19
|
+
|
20
|
+
<ul class="center">
|
21
|
+
<li>
|
22
|
+
<%= f.submit %>
|
23
|
+
</li>
|
24
|
+
</ul>
|
25
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% content_for :id, "profil" %>
|
2
|
+
|
3
|
+
<h1><%= t('user.index') %></h1>
|
4
|
+
|
5
|
+
<%= link_to t('user.edit.title'), user_edit_path if authorize_level?(2) %>
|
6
|
+
|
7
|
+
<div class="links">
|
8
|
+
<%= link_to_active "Home", root_path %>
|
9
|
+
<%= link_to_active t('user.index'), profile_path %>
|
10
|
+
<%= link_to_active t('layout.header.messages'), messages_path %>
|
11
|
+
<%= link_to_active t('layout.header.admin.files'), admin_files_path if authorize_level?(3) %>
|
12
|
+
<%= link_to_active t('layout.header.admin.pages'), admin_pages_path if authorize_level?(2) %>
|
13
|
+
<%= link_to_active t('layout.header.admin.events'), admin_events_path if authorize_level?(2) %>
|
14
|
+
<%= link_to_active t('layout.header.admin.activities'), admin_activities_path if authorize_level?(2) %>
|
15
|
+
<%= link_to_active t('layout.header.admin.galleries'), admin_galleries_path if authorize_level?(2) %>
|
16
|
+
<%= link_to_active t('layout.header.admin.messages'), admin_messages_path if authorize_level?(4) %>
|
17
|
+
<%= link_to_active t('layout.header.admin.newsletter_emails'), admin_newsletter_emails_path if authorize_level?(2) %>
|
18
|
+
<%= link_to_active t('layout.header.admin.downloads'), admin_downloads_path if authorize_level?(2) %>
|
19
|
+
<%= link_to_active t('layout.header.admin.users'), admin_users_path if authorize_level?(1) %>
|
20
|
+
</div>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
get 'profile', to: "users#profile"
|
4
|
+
|
5
|
+
patch 'user/update', to: "users#update"
|
6
|
+
get 'user/edit', to: "users#edit"
|
7
|
+
|
8
|
+
get 'login', to: "sessions#new"
|
9
|
+
delete 'signout', to: 'sessions#destroy'
|
10
|
+
resources :sessions, only: [:create]
|
11
|
+
|
12
|
+
namespace :admin do
|
13
|
+
|
14
|
+
resources :users, except: [:show]
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Snapuser
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
initializer "Snapuser.append_migrations" do |app|
|
5
|
+
unless app.root.to_s.match root.to_s
|
6
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
7
|
+
app.config.paths["db/migrate"] << expanded_path
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
data/lib/snapuser.rb
ADDED
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snapuser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- khcr
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bcrypt-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A rails engine to add a simple authentification and permission system.
|
56
|
+
email:
|
57
|
+
- kocher.ke@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- Rakefile
|
64
|
+
- app/controllers/admin/users_controller.rb
|
65
|
+
- app/controllers/sessions_controller.rb
|
66
|
+
- app/controllers/users_controller.rb
|
67
|
+
- app/helpers/sessions_helper.rb
|
68
|
+
- app/models/user.rb
|
69
|
+
- app/views/admin/users/_form.html.erb
|
70
|
+
- app/views/admin/users/edit.html.erb
|
71
|
+
- app/views/admin/users/index.html.erb
|
72
|
+
- app/views/admin/users/new.html.erb
|
73
|
+
- app/views/sessions/new.html.erb
|
74
|
+
- app/views/users/_form.html.erb
|
75
|
+
- app/views/users/edit.html.erb
|
76
|
+
- app/views/users/profile.html.erb
|
77
|
+
- config/routes.rb
|
78
|
+
- db/migrate/20150415193853_create_users.rb
|
79
|
+
- lib/snapuser.rb
|
80
|
+
- lib/snapuser/engine.rb
|
81
|
+
- lib/snapuser/version.rb
|
82
|
+
- lib/tasks/snapuser_tasks.rake
|
83
|
+
homepage: https://github.com/khcr/snapuser
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.4.6
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: A rails engine to add a simple authentification and permission system.
|
107
|
+
test_files: []
|