cornflakeomnisocial 0.1.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # OmniSocial
2
+
3
+ A Rails 3 engine for Twitter and Facebook logins using [OmniAuth](http://github.com/intridea/omniauth)
4
+
5
+ ## Installation
6
+
7
+ To use OmniSocial in a Rails 3 application:
8
+
9
+ 1. Require it in the Gemfile: `gem 'omnisocial'`
10
+
11
+ 2. Install it by running `bundle`.
12
+
13
+ 3. Run `rails g omnisocial` to copy an initializer and some CSS and image assets into your base application directory.
14
+
15
+ 4. Edit `config/initializers/omnisocial.rb` and include your application's Twitter and Facebook OAuth configuration.
16
+
17
+ 5. Run `rake db:migrate` to create the user and login_account tables.
18
+
19
+ 6. Test that the logins work by accessing `/login` inside your application.
20
+
21
+ Some more detailed installation instructions are in the [project announcement article](http://icelab.com.au/articles/welcome-to-the-omnisocial/).
22
+
23
+ ## Copyright & License
24
+
25
+ OmniSocial is Copyright (c) 2010 [Tim Riley](http://openmonkey.com/) and [Icelab](http://icelab.com.au/), and is released under MIT License.
26
+
27
+ The "Sign in with Twitter/Facebook" buttons are from [Komodo Media](http://www.komodomedia.com/blog/2009/05/sign-in-with-twitter-and-facebook-buttons/), distributeed under the [Creative Commons Attribution-Share Alike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/).
28
+
29
+ The twitter bird image is courtesy of [Pasquale D’Silva](http://wefunction.com/2008/07/freebie-twitter-icons-illustration/).
30
+
@@ -0,0 +1,55 @@
1
+ module Omnisocial
2
+ class AuthController < ApplicationController
3
+
4
+ unloadable
5
+
6
+ def new
7
+ if current_user?
8
+ flash[:notice] = 'You are already signed in. Please sign out if you want to sign in as a different user.'
9
+ redirect_to(root_path)
10
+ end
11
+ end
12
+
13
+ def callback
14
+ @account = case request.env['rack.auth']['provider']
15
+ when 'twitter' then
16
+ Omnisocial::TwitterAccount.find_or_create_from_auth_hash(request.env['rack.auth'])
17
+ when 'facebook' then
18
+ Omnisocial::FacebookAccount.find_or_create_from_auth_hash(request.env['rack.auth'])
19
+ end
20
+ if current_user && @account.user != current_user
21
+ @account.update_attributes(:user => current_user)
22
+ end
23
+ if @account.user
24
+ self.current_user = @account.user
25
+ flash[:message] = 'You have logged in successfully.'
26
+ redirect_back_or_default(root_path)
27
+ else
28
+ @user = ::User.new(:display_name => @account.name)
29
+ end
30
+ end
31
+
32
+ def confirm
33
+ @account = Omnisocial::LoginAccount.find(params[:account_id])
34
+ @user = ::User.new(params[:user].merge(:picture_url => @account.picture_url))
35
+ if @user.save
36
+ @account.update_attributes(:user => @user)
37
+ self.current_user = @user
38
+ flash[:message] = 'You have logged in successfully.'
39
+ redirect_back_or_default(root_path)
40
+ else
41
+ render :action => "callback"
42
+ end
43
+ end
44
+
45
+ def failure
46
+ flash[:error] = "We had trouble signing you in. Did you make sure to grant access? Please select a service below and try again."
47
+ render :action => 'new'
48
+ end
49
+
50
+ def destroy
51
+ logout!
52
+ redirect_to(session['return_to'] || root_path)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ module Omnisocial
2
+ module AuthHelper
3
+ def auth_request_path(options = {})
4
+ "/auth/#{options[:service]}"
5
+ end
6
+
7
+ def big_twitter_login_button
8
+ content_tag(:a, content_tag(:span, 'Sign in with Twitter'), :class => 'omnisocial-button twitter', :href => auth_request_path(:service => 'twitter'))
9
+ end
10
+
11
+ def big_facebook_login_button
12
+ content_tag(:a, content_tag(:span, 'Sign in with Facebook'), :class => 'omnisocial-button facebook', :href => auth_request_path(:service => 'facebook'))
13
+ end
14
+
15
+ def twitter_login_button
16
+ content_tag(:a, content_tag(:img, :src => '/images/omnisocial/signin_twitter.png', :alt => 'Sign in with Twitter'), :href => auth_request_path(:service => 'twitter'))
17
+ end
18
+
19
+ def facebook_login_button
20
+ content_tag(:a, content_tag(:img, :src => '/images/omnisocial/signin_facebook.png', :alt => 'Sign in with Facebook'), :href => auth_request_path(:service => 'facebook'))
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Omnisocial
2
+ class FacebookAccount < LoginAccount
3
+ def assign_account_info(auth_hash)
4
+ self.token = auth_hash['credentials']['token']
5
+ self.remote_account_id = auth_hash['uid']
6
+ self.login = auth_hash['user_info']['nickname']
7
+ self.name = auth_hash['user_info']['name']
8
+ self.picture_url = generate_picture_url
9
+ end
10
+
11
+ def account_url
12
+ "http://facebook.com/#{self.login}"
13
+ end
14
+
15
+ def generate_picture_url
16
+ if self.login.include?('profile.php')
17
+ "https://graph.facebook.com/#{self.login.gsub(/[^\d]/, '')}/picture?type=square"
18
+ else
19
+ "https://graph.facebook.com/#{self.login}/picture?type=square"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module Omnisocial
2
+ class LoginAccount
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ referenced_in :user
7
+
8
+ field :token
9
+ field :secret
10
+ field :remote_account_id
11
+ field :name
12
+ field :login
13
+ field :picture_url
14
+
15
+ def self.find_or_create_from_auth_hash(auth_hash)
16
+ if (account = first(:conditions => {:remote_account_id => auth_hash['uid']}))
17
+ account.assign_account_info(auth_hash)
18
+ account.save
19
+ account
20
+ else
21
+ create_from_auth_hash(auth_hash)
22
+ end
23
+ end
24
+
25
+ def self.create_from_auth_hash(auth_hash)
26
+ account = create!
27
+ account.assign_account_info(auth_hash)
28
+ account.save
29
+ account
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ module Omnisocial
2
+ class TwitterAccount < LoginAccount
3
+ def assign_account_info(auth_hash)
4
+ self.token = auth_hash['credentials']['token']
5
+ self.secret = auth_hash['credentials']['secret']
6
+ self.remote_account_id = auth_hash['uid']
7
+ self.login = auth_hash['user_info']['nickname']
8
+ self.picture_url = auth_hash['user_info']['image']
9
+ self.name = auth_hash['user_info']['name']
10
+ end
11
+
12
+ def account_url
13
+ "http://twitter.com/#{self.login}"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Omnisocial
2
+ class User
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ field :remember_token
7
+ field :display_name
8
+ field :email_address
9
+ field :picture_url
10
+
11
+ references_many :login_accounts, :class_name => 'Omnisocial::LoginAccount', :dependent => :destroy
12
+
13
+ validates_presence_of :display_name, :email_address
14
+
15
+ def facebook_account
16
+ login_accounts.select{|account| account.kind_of? FacebookAccount}.first
17
+ end
18
+
19
+ def from_facebook?
20
+ !!facebook_account
21
+ end
22
+
23
+ def from_twitter?
24
+ !!twitter_account
25
+ end
26
+
27
+ def twitter_account
28
+ login_accounts.select{|account| account.kind_of? TwitterAccount}.first
29
+ end
30
+
31
+ def remember
32
+ update_attributes(:remember_token => ::BCrypt::Password.create("#{Time.now}-#{self.login_accounts.first.type}-#{self.login_accounts.first.login}")) unless new_record?
33
+ end
34
+
35
+ def forget
36
+ update_attributes(:remember_token => nil) unless new_record?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ <%= form_for @user, :url => confirm_path(:account_id => @account) do |f| %>
2
+ <%= f.error_messages %>
3
+
4
+ <%= f.label :display_name %>:
5
+ <%= f.text_field :display_name %><br />
6
+
7
+ <%= f.label :email_address %>:
8
+ <%= f.text_field :email_address %><br />
9
+
10
+ <%= f.submit %>
11
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <div id="omnisocial-login">
2
+ <% if flash[:error] -%>
3
+ <div class="error">
4
+ <p>
5
+ <%= flash[:error] %>
6
+ </p>
7
+ </div>
8
+ <% end -%>
9
+ <div class="information">
10
+ <h1>Sign in (or up)</h1>
11
+ <p class="large">
12
+ You can use either your Twitter or Facebook account to sign in or sign up.
13
+ </p>
14
+ <p>
15
+ Select your preferred method and you'll be sent off to authorise us to use your account.
16
+ </p>
17
+ <p>
18
+ It&#8217;ll only take a second and your information will be perfectly safe. We don't get access to your password and <em>we won't post or tweet anything from your account</em> without your explicit permission.
19
+ </p>
20
+ </div>
21
+ <%= big_twitter_login_button %>
22
+ <%= big_facebook_login_button %>
23
+ </div>
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ Rails::Application.routes.draw do
2
+ match '/login' => 'omnisocial/auth#new', :as => :login
3
+ match '/auth/:service/callback' => 'omnisocial/auth#callback'
4
+ match '/auth/confirm/:account_id' => 'omnisocial/auth#confirm', :as => :confirm
5
+ match '/auth/failure' => 'omnisocial/auth#failure'
6
+ match '/logout' => 'omnisocial/auth#destroy', :as => :logout
7
+ end
@@ -0,0 +1,62 @@
1
+ class ActionController::Base
2
+ def self.require_user(options = {})
3
+ raise Exception, "require_user cannot be called on ActionController::Base. Only it's subclasses" if self == ActionController::Base
4
+ prepend_before_filter :require_user, options
5
+ end
6
+
7
+ helper_method :current_user, :current_user?
8
+
9
+ protected
10
+
11
+ # Filters
12
+
13
+ def require_user
14
+ current_user.present? || deny_access
15
+ end
16
+
17
+ # Utils
18
+
19
+ def store_location
20
+ session[:return_to] = request.fullpath
21
+ end
22
+
23
+ def deny_access(url = nil)
24
+ store_location
25
+ redirect_to url || login_path
26
+ end
27
+
28
+ def redirect_back_or_default(default)
29
+ redirect_to(session[:return_to] || default)
30
+ session[:return_to] = nil
31
+ end
32
+
33
+ def current_user
34
+ @current_user ||= if session[:user_id]
35
+ User.first(:conditions => {:id => session[:user_id]})
36
+ elsif cookies[:remember_token]
37
+ User.first(:conditions => {:remember_token => cookies[:remember_token]})
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ def current_user?
44
+ !!current_user
45
+ end
46
+
47
+ def current_user=(user)
48
+ user.tap do |user|
49
+ user.remember
50
+ session[:user_id] = user.id
51
+ cookies[:remember_token] = user.remember_token
52
+ end
53
+ end
54
+
55
+ def logout!
56
+ session[:user_id] = nil
57
+ @current_user = nil
58
+ cookies.delete(:remember_token)
59
+ session[:return_to] = nil
60
+ end
61
+
62
+ end
@@ -0,0 +1,35 @@
1
+ require 'rails/generators'
2
+
3
+ module Omnisocial
4
+ module Generators
5
+ class OmnisocialGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ desc 'Creates an omnisocial initializer and copies image and CSS assets.'
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), 'templates')
12
+ end
13
+
14
+ def copy_initializer
15
+ template 'omnisocial.rb', 'config/initializers/omnisocial.rb'
16
+ end
17
+
18
+ def copy_user_model
19
+ template 'user.rb', 'app/models/user.rb'
20
+ end
21
+
22
+ def copy_assets
23
+ copy_file 'assets/stylesheets/omnisocial.css', 'public/stylesheets/omnisocial.css'
24
+ copy_file 'assets/images/twitter.gif', 'public/images/omnisocial/twitter.gif'
25
+ copy_file 'assets/images/facebook.png', 'public/images/omnisocial/facebook.png'
26
+ copy_file 'assets/images/signin_twitter.png', 'public/images/omnisocial/signin_twitter.png'
27
+ copy_file 'assets/images/signin_facebook.png', 'public/images/omnisocial/signin_facebook.png'
28
+ end
29
+
30
+ def show_readme
31
+ readme 'README' if behavior == :invoke
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+
2
+ ===============================================================================
3
+
4
+ Welcome to the OmniSocial.
5
+
6
+ ===============================================================================
@@ -0,0 +1,68 @@
1
+ #omnisocial-login {
2
+ overflow: hidden;
3
+ }
4
+
5
+ #omnisocial-login .information {
6
+ float: left;
7
+ margin-right: 40px;
8
+ width: 450px;
9
+ }
10
+
11
+ a.omnisocial-button {
12
+ text-decoration: none;
13
+ }
14
+ a.omnisocial-button span {
15
+ -webkit-border-radius: 3px;
16
+ -moz-border-radius: 3px;
17
+ border-width: 1px;
18
+ border-style: solid;
19
+ font-weight: bold;
20
+ font-family: "proxima-nova-condensed-1", "proxima-nova-condensed-2", Helvetica, Arial, Verdana, sans-serif;
21
+ font-size: 16px;
22
+ cursor: pointer;
23
+ display: inline-block;
24
+ line-height: 1;
25
+ margin-top: 1px;
26
+ padding: 8px 10px 9px;
27
+ position: relative;
28
+ text-decoration: none;
29
+ text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0px;
30
+ background: #3583cf;
31
+ background: -webkit-gradient(linear, left top, left bottom, from(#629ed9), to(#3583cf));
32
+ border-color: #bbe2f8;
33
+ color: white;
34
+ float: none;
35
+ font-size: 18px;
36
+ position: absolute;
37
+ }
38
+ a:hover.omnisocial-button span {
39
+ text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0px;
40
+ background: #6ca520;
41
+ background: -webkit-gradient(linear, left top, left bottom, from(#90bb58), to(#6ca520));
42
+ border-color: #dcf1bf;
43
+ -o-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
44
+ -webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
45
+ -moz-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
46
+ box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
47
+ }
48
+
49
+ a.omnisocial-button.twitter {
50
+ background: url(/images/omnisocial/twitter.gif) center center no-repeat;
51
+ float: left;
52
+ height: 255px;
53
+ width: 200px;
54
+ }
55
+ a.omnisocial-button.twitter span {
56
+ margin: 240px 0 0 25px;
57
+ }
58
+
59
+ a.omnisocial-button.facebook {
60
+ background: url(/images/omnisocial/facebook.png) center center no-repeat;
61
+ float: left;
62
+ margin-left: 40px;
63
+ height: 255px;
64
+ width: 200px;
65
+ }
66
+ a.omnisocial-button.facebook span {
67
+ margin: 240px 0 0 11px;
68
+ }
@@ -0,0 +1,19 @@
1
+ Omnisocial.setup do |config|
2
+
3
+ # ==> Twitter
4
+ # config.twitter 'APP_KEY', 'APP_SECRET'
5
+
6
+ # ==> Facebook
7
+ # config.facebook 'APP_KEY', 'APP_SECRET', :scope => 'publish_stream'
8
+
9
+ if Rails.env.production?
10
+
11
+ # Configs for production mode go here
12
+
13
+ elsif Rails.env.development?
14
+
15
+ # Configs for development mode go here
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ class User < Omnisocial::User
2
+ # Make any customisations here
3
+ end
data/lib/omnisocial.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Omnisocial
2
+ require 'omnisocial/service_config'
3
+
4
+ # Twitter & Facebook app configs
5
+ mattr_accessor :service_configs
6
+ @@service_configs = {}
7
+
8
+ def self.setup
9
+ yield self
10
+ end
11
+
12
+ # config.twitter APP_KEY, APP_SECRET, :scope => ['foo', 'bar']
13
+ def self.twitter(app_key, app_secret, options = {})
14
+ @@service_configs[:twitter] = Omnisocial::ServiceConfig.new(app_key, app_secret, options)
15
+ end
16
+
17
+ def self.facebook(app_key, app_secret, options = {})
18
+ @@service_configs[:facebook] = Omnisocial::ServiceConfig.new(app_key, app_secret, options)
19
+ end
20
+
21
+ require 'omnisocial/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
22
+ end
23
+
24
+ require 'extensions/action_controller/base'
@@ -0,0 +1,33 @@
1
+ require 'omnisocial'
2
+
3
+ require 'rails'
4
+ require 'action_controller'
5
+
6
+ require 'omniauth/core'
7
+ require 'omniauth/oauth'
8
+ require 'bcrypt'
9
+
10
+ module Omnisocial
11
+ class Engine < Rails::Engine
12
+
13
+ config.to_prepare do
14
+ ApplicationController.helper(Omnisocial::AuthHelper)
15
+ end
16
+
17
+ initializer 'omnisocial.load_middleware', :after=> :load_config_initializers do
18
+ if Omnisocial.service_configs[:twitter]
19
+ config.app_middleware.use ::OmniAuth::Strategies::Twitter,
20
+ Omnisocial.service_configs[:twitter].app_key,
21
+ Omnisocial.service_configs[:twitter].app_secret
22
+ end
23
+
24
+ if Omnisocial.service_configs[:facebook]
25
+ config.app_middleware.use ::OmniAuth::Strategies::Facebook,
26
+ Omnisocial.service_configs[:facebook].app_key,
27
+ Omnisocial.service_configs[:facebook].app_secret,
28
+ Omnisocial.service_configs[:facebook].options
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ require 'ostruct'
2
+
3
+ module Omnisocial
4
+ class ServiceConfig < OpenStruct
5
+ def initialize(app_key, app_secret, options)
6
+ super(
7
+ :app_key => app_key,
8
+ :app_secret => app_secret,
9
+ :options => options
10
+ )
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Omnisocial
2
+ VERSION = '0.1.2.3'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cornflakeomnisocial
3
+ version: !ruby/object:Gem::Version
4
+ hash: 73
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ - 3
11
+ version: 0.1.2.3
12
+ platform: ruby
13
+ authors:
14
+ - Jason Kotchoff
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-01-10 00:00:00 +11:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 31
29
+ segments:
30
+ - 0
31
+ - 1
32
+ - 2
33
+ version: 0.1.2
34
+ prerelease: false
35
+ type: :runtime
36
+ name: oa-core
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 31
45
+ segments:
46
+ - 0
47
+ - 1
48
+ - 2
49
+ version: 0.1.2
50
+ prerelease: false
51
+ type: :runtime
52
+ name: oa-oauth
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 1
61
+ segments:
62
+ - 2
63
+ - 1
64
+ version: "2.1"
65
+ prerelease: false
66
+ type: :runtime
67
+ name: bcrypt-ruby
68
+ version_requirements: *id003
69
+ description: Twitter and Facebook logins for your Rails application.
70
+ email: jason@projectproject.com.au
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - README.md
79
+ - lib/generators/omnisocial/templates/omnisocial.rb
80
+ - lib/generators/omnisocial/templates/assets/images/signin_twitter.png
81
+ - lib/generators/omnisocial/templates/assets/images/twitter.gif
82
+ - lib/generators/omnisocial/templates/assets/images/signin_facebook.png
83
+ - lib/generators/omnisocial/templates/assets/images/facebook.png
84
+ - lib/generators/omnisocial/templates/assets/stylesheets/omnisocial.css
85
+ - lib/generators/omnisocial/templates/README
86
+ - lib/generators/omnisocial/templates/user.rb
87
+ - lib/generators/omnisocial/omnisocial_generator.rb
88
+ - lib/omnisocial/service_config.rb
89
+ - lib/omnisocial/version.rb
90
+ - lib/omnisocial/engine.rb
91
+ - lib/omnisocial.rb
92
+ - lib/extensions/action_controller/base.rb
93
+ - app/models/omnisocial/login_account.rb
94
+ - app/models/omnisocial/twitter_account.rb
95
+ - app/models/omnisocial/facebook_account.rb
96
+ - app/models/omnisocial/user.rb
97
+ - app/helpers/omnisocial/auth_helper.rb
98
+ - app/views/omnisocial/auth/new.html.erb
99
+ - app/views/omnisocial/auth/callback.html.erb
100
+ - app/controllers/omnisocial/auth_controller.rb
101
+ - config/routes.rb
102
+ has_rdoc: true
103
+ homepage: http://github.com/icelab/omnisocial
104
+ licenses: []
105
+
106
+ post_install_message:
107
+ rdoc_options: []
108
+
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 3
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ requirements: []
130
+
131
+ rubyforge_project:
132
+ rubygems_version: 1.3.7
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: Twitter and Facebook logins for your Rails application.
136
+ test_files: []
137
+