I'd like to write a function that checks if user's login and hashed password exists in database. Let's assume DB is very simple:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
User
login String
passHash Hash
UniqueL login
deriving Eq Show
Where Hash is an alias type Hash = PasswordHash PBKDF2 from https://hackage.haskell.org/package/password-2.0.1.1/docs/Data-Password-PBKDF2.html.
Also, for simplicity let's assume that both login and password are passed to my function as String.
There's a function in the module called checkPassword (https://hackage.haskell.org/package/password-2.0.1.1/docs/Data-Password-PBKDF2.html#g:3) that checks if a password produces the required hash. However, I don't know how can I use it in esqualeto where_ clause.
I came up with something like this:
type DB m a = ReaderT SqlBackend m a
checkCredentials ::(MonadIO m, MonadLogger m) => (String, String) -> DB m Bool
checkCredentials (login, password) = do
let hashFunc = (checkPassword $ mkPassword (pack password))
res <-
select $
from $ \user -> do
-- This won't wwork
where_ (user ^. UserLogin ==. val login &&. hashFunc (user ^. UserPassHash) ==. val PasswordCheckSuccess)
return user
return (negate $ null res)
but the part hashFunc (user ^. UserPassHash) obviously won't work. I guess I need to enter with my hashFunc into a monad (or two), but I have no idea how to do this.
I noticed that UserPassHash is of type EntityField User Hash. I wonder how can I turn it into EntityField User PasswordCheck.
Related
#nextcord.slash_command(name = 'avatar', description = f'🎴 Display your avatar or a specific user avatar.')
async def get_user_avatar(self, ctx, user: nextcord.Member = None)
I want to have a slash command with a name like this: " user avatar " with a space between this words.
You can't, slash_command names needs to be lowercase, between 1 and 32 characters long, and only consist of these symbols: a-z, 0-9, -, _, and other languages'/scripts' symbols.
Your best option would be to change it to: user_avatar.
I am trying to read from a file correctly in Haskell but I seem to get this error.
*** Exception: neo.txt: openFile: resource busy (file is locked)
This is my code.
import Data.Char
import Prelude
import Data.List
import Text.Printf
import Data.Tuple
import Data.Ord
import Control.Monad
import Control.Applicative((<*))
import Text.Parsec
( Parsec, ParseError, parse -- Types and parser
, between, noneOf, sepBy, many1 -- Combinators
, char, spaces, digit, newline -- Simple parsers
)
These are the movie fields.
type Title = String
type Director = String
type Year = Int
type UserRatings = (String,Int)
type Film = (Title, Director, Year , [UserRatings])
type Period = (Year, Year)
type Database = [Film]
This is the Parsing of all the types in order to read correctly from the file
-- Parse a string to a string
stringLit :: Parsec String u String
stringLit = between (char '"') (char '"') $ many1 $ noneOf "\"\n"
-- Parse a string to a list of strings
listOfStrings :: Parsec String u [String]
listOfStrings = stringLit `sepBy` (char ',' >> spaces)
-- Parse a string to an int
intLit :: Parsec String u Int
intLit = fmap read $ many1 digit
-- Or `read <$> many1 digit` with Control.Applicative
stringIntTuple :: Parsec String u (String , Int)
stringIntTuple = liftM2 (,) stringLit intLit
film :: Parsec String u Film
film = do
-- alternatively `title <- stringLit <* newline` with Control.Applicative
title <- stringLit
newline
director <- stringLit
newline
year <- intLit
newline
userRatings <- stringIntTuple
newline
return (title, director, year, [userRatings])
films :: Parsec String u [Film]
films = film `sepBy` newline
This is the main program (write "main" in winghci to start the program)
-- The Main
main :: IO ()
main = do
putStr "Enter your Username: "
name <- getLine
filmsDatabase <- loadFile "neo.txt"
appendFile "neo.txt" (show filmsDatabase)
putStrLn "Your changes to the database have been successfully saved."
This is the loadFile function
loadFile :: FilePath -> IO (Either ParseError [Film])
loadFile filename = do
database <- readFile filename
return $ parse films "Films" database
the other txt file name is neo and includes some movies like this
"Blade Runner"
"Ridley Scott"
1982
("Amy",5), ("Bill",8), ("Ian",7), ("Kevin",9), ("Emma",4), ("Sam",7), ("Megan",4)
"The Fly"
"David Cronenberg"
1986
("Megan",4), ("Fred",7), ("Chris",5), ("Ian",0), ("Amy",6)
Just copy paste everything include a txt file in the same directory and test it to see the error i described.
Whoopsy daisy, being lazy
tends to make file changes crazy.
File's not closed, as supposed
thus the error gets imposed.
This small guile, by loadFile
is what you must reconcile.
But don't fret, least not yet,
I will show you, let's get set.
As many other functions that work with IO in System.IO, readFile doesn't actually consume any input. It's lazy. Therefore, the file doesn't get closed, unless all its content has been consumed (it's then half-closed):
The file is read lazily, on demand, as with getContents.
We can demonstrate this on a shorter example:
main = do
let filename = "/tmp/example"
writeFile filename "Hello "
contents <- readFile filename
appendFile filename "world!" -- error here
This will fail, since we never actually checked contents (entirely). If you get all the content (for example with printing, length or similar), it won't fail anymore:
main = do
let filename = "/tmp/example2"
writeFile filename "Hello "
content <- readFile filename
putStrLn content
appendFile filename "world!" -- no error
Therefore, we need either something that really closes the file, or we need to make sure that we've read all the contents before we try to append to the file.
For example, you can use withFile together with some "magic" function force that makes sure that the content really gets evaluated:
readFile' filename = withFile filename ReadMode $ \handle -> do
theContent <- hGetContents handle
force theContent
However, force is tricky to achieve. You could use bang patterns, but this will evaluate the list only to WHNF (basically just the first character). You could use the functions by deepseq, but that adds another dependency and is probably not allowed in your assignment/exercise.
Or you could use any function that will somehow make sure that all elements are evaluated or sequenced. In this case, we can use a small trick and mapM return:
readFile' filename = withFile filename ReadMode $ \handle -> do
theContent <- hGetContents handle
mapM return theContent
It's good enough, but you would use something like pipes or conduit instead in production.
The other method is to make sure that we've really used all the contents. This can be done by using another parsec parser method instead, namely runParserT. We can combine this with our withFile approach from above:
parseFile :: ParsecT String () IO a -> FilePath -> IO (Either ParseError a)
parseFile p filename = withFile filename ReadMode $ \handle ->
hGetContents handle >>= runParserT p () filename
Again, withFile makes sure that we close the file. We can use this now in your loadFilm:
loadFile :: FilePath -> IO (Either ParseError [Film])
loadFile filename = parseFile films filename
This version of loadFile won't keep the file locked anymore.
The problem is that readFile doesn't actually read the entire file into memory immediately; it opens the file and instantly returns a string. As you "look at" the string, behind the scenes the file is being read. So when readFile returns, the file it still open for reading, and you can't do anything else with it. This is called "lazy I/O", and many people consider it to be "evil" precisely because it tends to cause problems like the one you currently have.
There are several ways you can go about fixing this. Probably the simplest is to just force the whole string into memory before continuing. Calculating the length of the string will do that — but only if you "use" the length for something, because the length itself is lazy. (See how this rapidly becomes messy? This is why people avoid lazy I/O.)
The simplest thing you could try is printing the number of films loaded right before you try to append to the database.
main = do
putStr "Enter your Username: "
name <- getLine
filmsDatabase <- loadFile "neo.txt"
putStrLn $ "Loaded " ++ show (length filmsDatabase) ++ " films."
appendFile "neo.txt" (show filmsDatabase)
putStrLn "Your changes to the database have been successfully saved."
It's kind of evil that what looks like a simple print message is actually fundamental to making the code work though!
The other alternative is to save the new database under a different name, and then delete the old file and rename the new one over the top of the old one. This does have the advantage that if the program were to crash half way through saving, you haven't just lost all your stuff.
I'm using java ldap to access active directory, more specifically spring ldap.
a group search by objectGUID yields no results when the filter is encoded as specified in rfc2254.
this is the guid in its hex representation:
\49\00\f2\58\1e\93\69\4b\ba\5f\8b\86\54\e9\d8\e9
spring ldap encodes the filter like that:
(&(objectClass=group)(objectGUID=\5c49\5c00\5cf2\5c58\5c1e\5c93\5c69\5c4b\5cba\5c5f\5c8b\5c86\5c54\5ce9\5cd8\5ce9))
as mentioned in rfc2254 and in microsoft technet:
the character must be encoded as the backslash '' character (ASCII
0x5c) followed by the two hexadecimal digits representing the ASCII
value of the encoded character. The case of the two hexadecimal
digits is not significant.
Blockquote
so a backslash should be '\5c'
but I get no results with above filter from AD. also if I put that filter in AD management console custom filters it does not work.
when I remove the 5c from the filter it works both from java and in AD console.
Am I missing something here?
of course I can encode the filter without the 5c but I'm nt sure it the right way and I prefer to let spring encode the filters because it knows a lot of things that I should do manually.
I think the blog entry at:http://www.developerscrappad.com/1109/windows/active-directory/java-ldap-jndi-2-ways-of-decoding-and-using-the-objectguid-from-windows-active-directory/ provides the information you need.
i found solution with php to get user with objectGUID
etap one when i create user i put his objectGuid in bdd, the objectGuid that you see in the Ad ex $guid_str = "31207E1C-D81C-4401-8356-33FEF9C8A"
after i create my own function to transform this object id int hexadécimal
function guidToHex($guid_str){
$str_g= explode('-',$guid_str);
$str_g[0] = strrev($str_g[0]);
$str_g[1] = strrev($str_g[1]);
$str_g[2] = strrev($str_g[2]);
$retour = '\\';
$strrev = 0;
foreach($str_g as $str){
for($i=0;$i < strlen($str)+2; $i++){
if($strrev < 3)
$retour .= strrev(substr($str,0,2)).'\\' ;
else
$retour .= substr($str,0,2).'\\' ;
$str = substr($str,2);
}
if($strrev < 3)
$retour .= strrev($str);
else
$retour .= $str ;
$strrev++;
}
return $retour;
}
this function return me a string like \1C\7E\20\31\1C\D8\01\44\83\EF\9C\8A"\F9\ED\C2\7F after this i put this string in my filter and i get the user
#
to get format of objectGuid
i use this fonction that i foud it in internet
function convertBinToMSSQLGuid($binguid)
{
$unpacked = unpack('Va/v2b/n2c/Nd', $binguid);
return sprintf('%08X-%04X-%04X-%04X-%04X%08X', $unpacked['a'], $unpacked['b1'], $unpacked['b2'], $unpacked['c1'], $unpacked['c2'], $unpacked['d']);
}
i mean this format = 31207E1C-D81C-4401-8356-33FEF9C8A
Pass a byte array and search should work.
Update:
The only answer yet given is not helping me. The code works as desired on my local system but does not work in the deployed Python app. This is a series problem for me. Please give this question a serious second look.
Here is some simplified code to show what is happening. When the simplified code is put into the interactive console for the SDK, it always prints out Hello, schott.brian, but in the deployed app its like it prints out no match. What's up with that?
user = "schott.brian"
name = "schott.brian"
if user and user == name:
print "Hello, " + user
else:
print "no match"
Here is my code. Notice the second if checks if user and (user == person.user):
user = users.get_current_user()
ID_id = self.request.get("ID", None)
ID_id = ''.join(ID_id.split())
key = db.Key.from_path("PQ", ID_id)
person = PQ.get(key)
if person: #person's ID DOES exist already
logging.info("6 person %s" % person.user )
logging.info("6 key %s" % key )
logging.info("6 ID_id %s" % ID_id )
logging.info("6 user %s" % user )
if user and (user == person.user):
# never get here on gae, but works on sdk
else:
# always gets to here by mistake on gae, but works on SDKs
logging.info("7 user %s" % user )
logging.info("7 person %s" % person.user )
Here are the logs for that code on gae and even though user exists and
(user == person.user), that if clause is NOT succeeding. Can you tell me why? Does one of the two really include gmail.com and the other does not?
2012-07-17 15:39:19.993 6 person schott.brian
I 2012-07-17 15:39:19.993 6 key ag1zfnBhcnRpY2lwb2xschMLEgJQUSILY29kZUJTY2hvdHQM
I 2012-07-17 15:39:19.993 6 ID_id codeBSchott
I 2012-07-17 15:39:19.993 6 user schott.brian
I 2012-07-17 15:39:19.993 7 user schott.brian
I 2012-07-17 15:39:19.994 7 person schott.brian
user.get_current_user() returns an object. Printing the user casts it to a string, so maybe you want to do something like:
if user and (str(user) == str(person.user)):
but you're actually better off comparing user ids, rather than string representations of user objects.
In my django app, especially on the admin side, I do a few def's with my models:
def get_flora(self):
return self.flora.all()
def targeted_flora(self):
return u"%s" % (self.get_flora())
whereas flora is a ManyToManyField, however, sometimes ForeignKey fields are used also.
I do this to provide a utility 'get' function for the model, and then the second def is to provide django admin with a a friendlier field name to populate the tabular/list view.
Perhaps a two part question here:
1. Is this a good workflow/method for doing such things, and
2. The resultant string output in admin looks something like:
[<Species: pittosporum>, <Species: pinus radiata>]
Naturally enough, but how to make it look like:
pittosporum & pinus radiata
or, if there were three;
pittosporum, pinus radiata & erharta ercta
Super thanks!
Sounds like you want something like this:
def targeted_flora(self):
names= [f.name for f in self.get_flora()] # or however you get a floras name
if len(names) == 1:
return names[0]
else:
return ', '.join(names[:-1]) + ' & ' + names[-1]
This works btw:
def punctuated_object_list(objects, field):
if field:
field_list = [getattr(f, field) for f in objects]
else:
field_list = [str(f) for f in objects]
if len(field_list) > 0:
if len(field_list) == 1:
return field_list[0]
else:
return ', '.join(field_list[:-1]) + ' & ' + field_list[-1]
else:
return u''