forked from hubot-archive/hubot-auth
-
Notifications
You must be signed in to change notification settings - Fork 1
/
auth.coffee
162 lines (137 loc) · 5.76 KB
/
auth.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Description
# Assign roles to users and restrict command access in other scripts.
#
# Configuration:
# HUBOT_AUTH_ADMIN - A comma separate list of user IDs
#
# Commands:
# hubot <user> has <role> role - Assigns a role to a user
# hubot <user> doesn't have <role> role - Removes a role from a user
# hubot what roles does <user> have - Find out what roles a user has
# hubot what roles do I have - Find out what roles you have
# hubot who has <role> role - Find out who has the given role
# hubot list assigned roles - List all assigned roles
# hubot what is my name - Tells you your name from persistent storage
# hubot what is my id - tells you your id from persistent storage
#
# Notes:
# * Call the method: robot.auth.hasRole(msg.envelope.user,'<role>')
# * returns bool true or false
#
# * the 'admin' role can only be assigned through the environment variable
# * roles are all transformed to lower case
#
# * The script assumes that user IDs will be unique on the service end as to
# correctly identify a user. Names were insecure as a user could impersonate
# a user
config =
admin_list: process.env.HUBOT_AUTH_ADMIN
module.exports = (robot) ->
unless config.admin_list?
robot.logger.warning 'The HUBOT_AUTH_ADMIN environment variable not set'
if config.admin_list?
admins = config.admin_list.split ','
else
admins = []
class Auth
isAdmin: (user) ->
user.id.toString() in admins
hasRole: (user, roles) ->
userRoles = @userRoles(user)
if userRoles?
roles = [roles] if typeof roles is 'string'
for role in roles
return true if role in userRoles
return false
usersWithRole: (role) ->
users = []
for own key, user of robot.brain.data.users
if @hasRole(user, role)
users.push(user.name)
users
userRoles: (user) ->
roles = []
if user? and robot.auth.isAdmin user
roles.push('admin')
if user.roles?
roles = roles.concat user.roles
roles
robot.auth = new Auth
robot.respond /@?(.+) ha(?:s|ve) (["'\w: -_]+) role/i, (msg) ->
name = msg.match[1].trim()
if name.toLowerCase() is 'i' then name = msg.message.user.name
if name.match(/(.*)(?:don['’]t|doesn['’]t|do not|does not)/i) then return
unless name.toLowerCase() in ['', 'who', 'what', 'where', 'when', 'why']
unless robot.auth.isAdmin msg.message.user
msg.reply "Sorry, only admins can assign roles."
else
newRole = msg.match[2].trim().toLowerCase()
user = robot.brain.userForName(name)
return msg.reply "#{name} does not exist" unless user?
user.roles or= []
if newRole in user.roles
msg.reply "#{name} already has the '#{newRole}' role."
else
if newRole is 'admin'
msg.reply "Sorry, the 'admin' role can only be defined in the HUBOT_AUTH_ADMIN env variable."
else
myRoles = msg.message.user.roles or []
user.roles.push(newRole)
msg.reply "OK, #{name} has the '#{newRole}' role."
robot.respond /@?(.+) (?:don['’]t|doesn['’]t|do not|does not) have (["'\w: -_]+) role/i, (msg) ->
name = msg.match[1].trim()
if name.toLowerCase() is 'i' then name = msg.message.user.name
unless name.toLowerCase() in ['', 'who', 'what', 'where', 'when', 'why']
unless robot.auth.isAdmin msg.message.user
msg.reply "Sorry, only admins can remove roles."
else
newRole = msg.match[2].trim().toLowerCase()
user = robot.brain.userForName(name)
return msg.reply "#{name} does not exist" unless user?
user.roles or= []
if newRole is 'admin'
msg.reply "Sorry, the 'admin' role can only be removed from the HUBOT_AUTH_ADMIN env variable."
else
myRoles = msg.message.user.roles or []
user.roles = (role for role in user.roles when role isnt newRole)
msg.reply "OK, #{name} doesn't have the '#{newRole}' role."
robot.respond /what roles? do(es)? @?(.+) have\?*$/i, (msg) ->
name = msg.match[2].trim()
if name.toLowerCase() is 'i' then name = msg.message.user.name
user = robot.brain.userForName(name)
return msg.reply "#{name} does not exist" unless user?
userRoles = robot.auth.userRoles(user)
if userRoles.length == 0
msg.reply "#{name} has no roles."
else
msg.reply "#{name} has the following roles: #{userRoles.join(', ')}."
robot.respond /who has (["'\w: -_]+) role\?*$/i, (msg) ->
role = msg.match[1]
userNames = robot.auth.usersWithRole(role) if role?
if userNames.length > 0
msg.reply "The following people have the '#{role}' role: #{userNames.join(', ')}"
else
msg.reply "There are no people that have the '#{role}' role."
robot.respond /list assigned roles/i, (msg) ->
roles = []
unless robot.auth.isAdmin msg.message.user
msg.reply "Sorry, only admins can list assigned roles."
else
for i, user of robot.brain.data.users when user.roles
roles.push role for role in user.roles when role not in roles
if roles.length > 0
msg.reply "The following roles are available: #{roles.join(', ')}"
else
msg.reply "No roles to list."
robot.respond /what(?:'s|s|\s+is)\s+my\s+name\s*(?:\?|)/i, (msg) ->
user = robot.brain.userForId(msg.envelope.user['id'])
unless user and user['name']
msg.reply "Your user could not be found in my Brain, sorry!"
return
msg.reply "Your name is: #{user['name']}."
robot.respond /what(?:'s|s|\s+is)\s+my\s+id\s*(?:\?|)/i, (msg) ->
user = robot.brain.userForId(msg.envelope.user['id'])
unless user and user['id']
msg.reply "Your user could not be found in my Brain, sorry!"
return
msg.reply "Your ID is: #{user['id']}."