def add_user(first_name, last_name, username, password, email, timezone=None, preferred_languages=None): if password is None: password = generate_random_password() if preferred_languages is None or preferred_languages == "": preferred_languages = [] else: preferred_languages = [lang for lang in preferred_languages.split(",")] user = User( first_name=first_name, last_name=last_name, username=username, password=password, email=email, timezone=timezone, preferred_languages=preferred_languages ) try: with SessionGen() as session: session.add(user) session.commit() except IntegrityError: return False logger.info("Registered user {} with password {}".format(username, password)) return True
def add_admin(username, password=None): logger.info("Creating the admin on the database.") generated = False if password == EmptyPassword.GENERATE or password is None: password = generate_random_password() generated = True elif password == EmptyPassword.PROMPT: password = getpass.getpass() admin = Admin(username=username, authentication=hash_password(password), name=username, permission_all=True) try: with SessionGen() as session: session.add(admin) session.commit() except IntegrityError: logger.error("An admin with the given username already exists.") return False if generated: logger.info("Admin with complete access added. " "Login with username %s and password %s", username, password) else: logger.info("Admin with complete access added. " "Login with username %s and supplied password", username) return True
def add_user(first_name, last_name, username, password, email, timezone, preferred_languages): logger.info("Creating the user in the database.") if password is None: password = generate_random_password() if preferred_languages is None or preferred_languages == "": preferred_languages = "[]" else: preferred_languages = \ "[" + ",".join("\"" + lang + "\"" for lang in preferred_languages.split(",")) + "]" user = User(first_name=first_name, last_name=last_name, username=username, password=password, email=email, timezone=timezone, preferred_languages=preferred_languages) 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. " "Use AddParticipation to add this user to a contest.") return True
def post(self): try: username = self.get_argument("username") email = self.get_argument("email") if not 1 <= len(username): raise ValueError() if not 1 <= len(email): raise ValueError() except (tornado.web.MissingArgumentError, ValueError): raise tornado.web.HTTPError(400) # Check that the username exists tot_users = self.sql_session.query(User)\ .filter(User.username == username)\ .filter(User.email == email)\ .count() if tot_users == 0: # HTTP 409: Conflict raise tornado.web.HTTPError(409) if not hasattr(config, "saco_admin_email_password"): logger.error( "'saco_admin_email_password' not defined in cms.conf - can't email new password" ) return pwd = generate_random_password() self.sql_session.query(User)\ .filter(User.username == username)\ .filter(User.email == email)\ .update({'password': build_password(pwd)}) self.sql_session.commit() sender = '*****@*****.**' receivers = [email] message = password_reset_email_format.format(sender, email, pwd) result = 'successful' try: s = smtplib.SMTP('smtp.saco-evaluator.org.za', 587) s.login('*****@*****.**', config.saco_admin_email_password) s.sendmail(sender, receivers + [sender], message) except smtplib.SMTPException as e: logger.error('Unable to send email:', e) result = 'unsuccessful' if hasattr(config, 'test_logs_dir'): with open(os.path.join(config.test_logs_dir, 'pwd_reset_requests'), 'a') as f: time = datetime.datetime.now().strftime('%y-%m-%d %H:%M') f.write('{} {} {} {}\n'.format(username, email, time, result)) else: logger.error( "test_logs_dir undefined in cms.conf, can't write logs")
class User(Base): """Class to store a user. """ __tablename__ = 'users' # Auto increment primary key. id = Column( Integer, primary_key=True) # Real name (human readable) of the user. first_name = Column( Unicode, nullable=False) last_name = Column( Unicode, nullable=False) # Username and password to log in the CWS. username = Column( Unicode, CodenameConstraint("username"), nullable=False, unique=True) password = Column( Unicode, nullable=False, default=lambda: build_password(generate_random_password())) # Email for any communications in case of remote contest. email = Column( Unicode, nullable=True) # Timezone for the user. All timestamps in CWS will be shown using # the timezone associated to the logged-in user or (if it's None # or an invalid string) the timezone associated to the contest or # (if it's None or an invalid string) the local timezone of the # server. This value has to be a string like "Europe/Rome", # "Australia/Sydney", "America/New_York", etc. timezone = Column( Unicode, nullable=True) # The language codes accepted by this user (from the "most # preferred" to the "least preferred"). If in a contest there is a # statement available in some of these languages, then the most # preferred of them will be highlighted. # FIXME: possibly move it to Participation and change it back to # primary_statements preferred_languages = Column( ARRAY(String), nullable=False, default=[])
def add_user(first_name, last_name, username, password, method, is_hashed, email, timezone, preferred_languages, overwrite=False): 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 or preferred_languages == "": preferred_languages = "[]" else: preferred_languages = \ "[" + ",".join("\"" + lang + "\"" for lang in preferred_languages.split(",")) + "]" user = User(first_name=first_name, last_name=last_name, username=username, password=stored_password, email=email, timezone=timezone, preferred_languages=preferred_languages) with SessionGen() as session: if overwrite: existing_user = session.query(User) \ .filter(User.username == username).first() if existing_user is not None: user = existing_user user.first_name = first_name user.last_name = last_name user.username = username if not pwd_generated: user.password = stored_password else: pwd_generated = False user.email = email or user.email user.timezone = timezone or user.timezone user.preferred_languages = preferred_languages or \ user.preferred_languages try: 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 add_admin(username, password=None, real_name=None): logger.info("Creating the admin on the database.") if password is None: password = generate_random_password() admin = Admin(username=username, authentication=hash_password(password), name=real_name or username, permission_all=True) try: with SessionGen() as session: session.add(admin) session.commit() except IntegrityError: logger.error("An admin with the given username already exists.") return False logger.info("Admin '%s' with complete access added. ", username) return True
def generate_passwords(contest_id, exclude_hidden, exclude_unrestricted, output_path): logger.info("Updating passwords...") with open(output_path, 'w') as io: io.write("contest_id,team,fullname,username,password\n") with SessionGen() as session: if contest_id is not None: contest = Contest.get_from_id(contest_id, session) objects = session.query(Participation).join( Participation.user).join(Participation.team) if exclude_unrestricted: objects = objects.filter( Participation.unrestricted == False) if exclude_hidden: objects = objects.filter(Participation.hidden == False) else: objects = session.query(User) for obj in objects: password = generate_random_password() obj.password = build_password(password, 'plaintext') user = obj if isinstance(obj, User) else obj.user fullname = "%s %s" % (user.first_name, user.last_name) if isinstance(obj, Participation): team = obj.team.code if obj.team is not None else '' logger.info( "Updating participation of user %s (team=%s) on contest id %d", user.username, team, contest.id) io.write( "%d,%s,%s,%s,%s\n" % (contest.id, team, fullname, user.username, password)) else: logger.info("Updating user %s", user.username) io.write(",,%s,%s,%s\n" % (fullname, user.username, password)) session.commit() logger.info("Done.") return True
def add_user(first_name, last_name, username, password, method, is_hashed, email, timezone, preferred_languages): 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 = [] else: preferred_languages = 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) 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 add_user(first_name, last_name, username, password, method, is_hashed, email, timezone, preferred_languages): 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 = [] else: preferred_languages = 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) 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 test_alphabet(self): self.assertRegex(generate_random_password(), r"^[a-z]*$")
def get(self): self.create_client() # When we have a code, request id token if self.get_argument('code', False): response = self.request.query response = self.client.parse_response( AuthorizationResponse, info=response, sformat="urlencoded") # The query is checked against the state in the cookie code = response['code'] if 'code' in response else None state = response['state'] if 'state' in response else None cookie = self.get_secure_cookie(self.contest.name + "_auth") if code and cookie and json.loads(cookie)[0] == state: args = { "code": code, "token_endpoint": self.op_info["token_endpoint"], "redirect_uri": self.redirect_uri, } # Request an access token to the authentication server resp = yield self.get_access_token( state=state, request_args=args, authn_method="client_secret_basic" ) else: self.redirect_login_error() self.clear_cookie(self.contest.name + "_auth") # The token is checked against the nonce in the cookie id_token = resp["id_token"] if id_token["nonce"] != json.loads(cookie)[1]: self.redirect_login_error() first_name = ( id_token["given_name"] if "given_name" in id_token else "") last_name = ( id_token["family_name"] if "family_name" in id_token else "") email = ( id_token["email"] if "email" in id_token else "") username = id_token["sub"] # Check if the user already exists user = self.sql_session.query(User)\ .filter(User.username == username).first() # Create the user if it doesn't exist yet if user is None: user = User( first_name, last_name, username, email=email, password=build_password(generate_random_password())) self.sql_session.add(user) self.sql_session.commit() if not [p for p in user.participations if p.contest_id == self.contest.id]: participation = Participation( contest=self.contest, user=user) self.sql_session.add(participation) self.sql_session.commit() self.try_user_login(user) # Request a code else: state = rndstr() nonce = rndstr() self.set_secure_cookie( self.contest.name + "_auth", json.dumps([state, nonce]), expires_days=None) claims_request = ClaimsRequest( id_token=Claims( sub={"essential": True} ), userinfo=Claims( given_name={"essential": True}, family_name={"essential": True}, preferred_username={"essential": True}, ) ) args = { "client_id": self.client.client_id, "response_type": "code", "scope": ["openid", "offline_access"], "nonce": nonce, "redirect_uri": self.redirect_uri, "state": state, "claims": claims_request, } next_page = self.get_argument('next', None) if next_page: args["next"] = next_page auth_req = (self.client.construct_AuthorizationRequest (request_args=args)) login_url = auth_req.request( self.op_info["authorization_endpoint"]) self.redirect(login_url)
def test_random(self): self.assertNotEqual(generate_random_password(), generate_random_password())
def post(self): fallback_page = self.url("users", "import") r_params = self.render_params() action = self.get_body_argument('action', 'upload') if action == 'upload': ignore_existing = self.get_body_argument('ignore_existing', False) generate_passwords = self.get_body_argument( 'generate_passwords', False) ignored = 0 try: user_csv = self.request.files["users_csv"][0] users = CsvUserLoader(None, None, user_csv['body']).get_users() processed_users = [] for user in users: if generate_passwords or callable(user.password): user.password = None db_user = self.sql_session.query(User).filter_by( username=user.username).first() if db_user: if ignore_existing: if db_user.password: db_user.password = '******' processed_users.append((False, db_user)) ignored += 1 else: self.application.service.add_notification( make_datetime(), 'Import failed', 'User "%s" already exists' % user.username) self.redirect(fallback_page) return else: processed_users.append((True, user)) if ignored: self.application.service.add_notification( make_datetime(), "User exists", '%d users already exist, ignored' % ignored) r_params['users'] = processed_users self.render("users_import_preview.html", **r_params) return except Exception as error: self.application.service.add_notification( make_datetime(), "Bad CSV file", repr(error)) self.redirect(fallback_page) return elif action == 'save': usernames = self.get_body_arguments('username', False) first_names = self.get_body_arguments('first_name', False) last_names = self.get_body_arguments('last_name', False) passwords = self.get_body_arguments('password', False) emails = self.get_body_arguments('email', False) for i in range(len(usernames)): args = { 'username': usernames[i], 'first_name': first_names[i], 'last_name': last_names[i], 'email': emails[i], } if passwords[i]: args['password'] = passwords[i] else: args['password'] = crypto.generate_random_password() args['password'] = crypto.hash_password(args['password'], method='plaintext') user = User(**args) self.sql_session.add(user) if self.try_commit(): # Create the user on RWS. self.application.service.proxy_service.reinitialize() self.redirect(self.url("users")) return else: self.redirect(fallback_page) return self.redirect(fallback_page)
def load_participations(path): logger.info("Loading...") with open(path, 'r') as io: data = json.load(io) participations = data['participations'] with SessionGen() as session: for entry in participations: logger.info('Loading: %s' % (entry)) contest = Contest.get_from_id(entry['contest_id'], session) if contest is None: logger.error(" Contest ID %d not found" % (entry['contest_id'])) session.rollback() return False userdata = entry['user'] user = session.query(User).filter( User.username == userdata['username']).first() if user is None: user = User(username=userdata['username'], first_name=userdata['first_name'], last_name=userdata['last_name'], password=build_password( generate_random_password())) logger.info(' Creating new user: %s' % (user.username)) session.add(user) else: logger.info(' Using existing user: %s (id=%d)' % (user.username, user.id)) if 'plaintext_password' in userdata: logger.info(' * password') user.password = build_password(userdata['plaintext_password'], 'plaintext') if 'first_name' in userdata: logger.info(' * first_name: %s' % (userdata['first_name'])) user.first_name = userdata['first_name'] if 'last_name' in userdata: logger.info(' * last_name: %s' % (userdata['last_name'])) user.last_name = userdata['last_name'] participation = session.query(Participation).join( Participation.user).filter( Participation.contest == contest).filter( User.username == user.username).first() if participation is None: participation = Participation(user=user, contest=contest) logger.info( ' Creating new participation for contest_id=%d user=%s' % (contest.id, user.username)) session.add(participation) else: logger.info( ' Updating participation: id=%d contest_id=%d user=%s' % (participation.id, participation.contest_id, participation.user.username)) if 'plaintext_password' in entry: logger.info(' * plaintext_password') participation.password = build_password( entry['plaintext_password'], 'plaintext') if 'ip' in entry: logger.info(' * ip: %s' % (entry['ip'])) participation.ip = [ipaddress.ip_network(entry['ip'])] if 'delay_time' in entry: logger.info(' * delay_time: %d' % (entry['delay_time'])) participation.delay_time = datetime.timedelta( seconds=entry['delay_time']) if 'extra_time' in entry: logger.info(' * extra_time: %d' % (entry['extra_time'])) participation.extra_time = datetime.timedelta( seconds=entry['extra_time']) if 'hidden' in entry: logger.info(' * hidden: %s' % (entry['hidden'])) participation.hidden = entry['hidden'] if 'unrestricted' in entry: logger.info(' * unrestricted: %s' % (entry['unrestricted'])) participation.unrestricted = entry['unrestricted'] if 'team' in userdata: team = session.query(Team).filter( Team.code == userdata['team']['code']).first() if team is None: team = Team(code=userdata['team']['code'], name=userdata['team']['name']) logger.info(' Creating new team: %s' % (team.code)) session.add(team) else: logger.info(' Using existing team: %s' % (team.code)) if 'name' in userdata['team']: logger.info(' * name: %s' % (userdata['team']['name'])) team.name = userdata['team']['name'] participation.team = team session.commit() logger.info("Done.") return True