-
Notifications
You must be signed in to change notification settings - Fork 405
Expand file tree
/
Copy pathAddUser.py
More file actions
executable file
·140 lines (119 loc) · 4.98 KB
/
AddUser.py
File metadata and controls
executable file
·140 lines (119 loc) · 4.98 KB
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
#!/usr/bin/env python3
# Contest Management System - http://cms-dev.github.io/
# Copyright © 2016 Stefano Maggiolo <s.maggiolo@gmail.com>
# Copyright © 2017-2018 Luca Wehrstedt <luca.wehrstedt@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""This script creates a new user in the database.
"""
# We enable monkey patching to make many libraries gevent-friendly
# (for instance, urllib3, used by requests)
import gevent.monkey
gevent.monkey.patch_all() # noqa
import argparse
import logging
import sys
from sqlalchemy.exc import IntegrityError
from cms import utf8_decoder
from cms.db import SessionGen, User
from cmscommon.crypto import generate_random_password, build_password, \
hash_password
logger = logging.getLogger(__name__)
def add_user(
first_name: str,
last_name: str,
username: str,
password: str | None,
method: str,
is_hashed: bool,
email: str | None,
timezone: str | None,
preferred_languages: str | None,
):
logger.info("Creating the user in the database.")
pwd_generated = False
if password is None:
assert not is_hashed
password = generate_random_password()
pwd_generated = True
if is_hashed:
stored_password = build_password(password, method)
else:
stored_password = hash_password(password, method)
if preferred_languages is None:
preferred_languages_l = []
else:
preferred_languages_l = list(
lang.strip() for lang in preferred_languages.split(",") if lang.strip()
)
user = User(
first_name=first_name,
last_name=last_name,
username=username,
password=stored_password,
email=email,
timezone=timezone,
preferred_languages=preferred_languages_l,
)
try:
with SessionGen() as session:
session.add(user)
session.commit()
except IntegrityError:
logger.error("A user with the given username already exists.")
return False
logger.info("User added%s. "
"Use AddParticipation to add this user to a contest."
% (" with password %s" % password if pwd_generated else ""))
return True
def main():
"""Parse arguments and launch process.
"""
parser = argparse.ArgumentParser(description="Add a user to CMS.")
parser.add_argument("first_name", action="store", type=utf8_decoder,
help="given name of the user")
parser.add_argument("last_name", action="store", type=utf8_decoder,
help="family name of the user")
parser.add_argument("username", action="store", type=utf8_decoder,
help="username used to log in")
parser.add_argument("-e", "--email", action="store", type=utf8_decoder,
help="email of the user")
parser.add_argument("-t", "--timezone", action="store", type=utf8_decoder,
help="timezone of the user, e.g. Europe/London")
parser.add_argument("-l", "--languages", action="store", type=utf8_decoder,
help="comma-separated list of preferred languages")
password_group = parser.add_mutually_exclusive_group()
password_group.add_argument(
"-p", "--plaintext-password", action="store", type=utf8_decoder,
help="password of the user in plain text")
password_group.add_argument(
"-H", "--hashed-password", action="store", type=utf8_decoder,
help="password of the user, already hashed using the given algorithm "
"(currently only --bcrypt)")
method_group = parser.add_mutually_exclusive_group()
method_group.add_argument(
"--bcrypt", dest="method", action="store_const", const="bcrypt",
help="whether the password will be stored in bcrypt-hashed format "
"(if omitted it will be stored in plain text)")
args = parser.parse_args()
if args.hashed_password is not None and args.method is None:
parser.error("hashed password given but no method specified")
success = add_user(args.first_name, args.last_name, args.username,
args.plaintext_password or args.hashed_password,
args.method or "plaintext",
args.hashed_password is not None, args.email,
args.timezone, args.languages)
return 0 if success is True else 1
if __name__ == "__main__":
sys.exit(main())